本文主要是介绍Three Integers(暴力,行走在TLE的边缘),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
VJ链接
题意:
对三个数a,b,c,进行若干次操作,每次操作只能对其中一个数进行+1或-1。同一个数可进行多次操作。问使得b能整除a且c能整除b的最少操作次数。(1≤a≤b≤c≤10000)
思路:
由于数据范围较小,且a和c都可以用b求得,可以暴力枚举b的所有情况,然后记录每种情况需要进行操作的次数。保留最小的一组即可。就是假设b已知的情况下去推a和c。
具体做法:
1.a用b来表示以及对a操作的次数实现:
b既定时,由于a%b==0,则a必然是b的因数,枚举b的所有因数,其中与a差值最小的那个因数即为最终的a,它们的差值就是需要对题中输入的a的操作次数。
注意枚举b的因数时,范围取1~sqrt(b),每次计算两个数
2.c用b表示以及对c的操作次数实现:
c=k*b(k=1,2,3,4…), 求与c最接近的b的整数倍即可,略
3 关于b的枚举范围:1~c+r ,r是个大概值,用于容错,实测200即可
但是r一定要有,为什么?我也不知道我为什么wa了六次,有明白的大佬希望能艾特我,不胜感激。
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;
int t,q,w,e;
int ab(int x) //绝对值
{return x=x>0?x:-1*x;
}
int sea(int x,int sp) //寻找与sp最接近的,x的因数值
{int mn=inf,s,j,r;for(int i=1; i<=sqrt(x); i++)if(x%i==0){j=x/i; //i,j,一次算俩r=ab(i-sp);if(mn>r){mn=r;s=i;}r=ab(j-sp);if(mn>r){mn=r;s=j;}}return s;
}
int main()
{scanf("%d",&t);while(t--){scanf("%d%d%d",&q,&w,&e);int X,Y,Z,minn=inf,y,y1; //X,Y,Z最终保留的abc值,minn:最少操作次数for(int k=1; k<=e+100; k++) //b的范围,一定要扩充一下{int ans=0,a=q,b=w,c=e;//ans:每次的操做次数和ans+=ab(b-k);//b需要的操作数b=k;if(c%k!=0)//省时间{y=c/k*k;ans+=min(c-y,y+k-c);c=(c-y)>(y+k-c)?y+k:y;//b求c}if(b%a!=0){y1=sea(k,a);//b求aans+=ab(y1-a);a=y1;}if(minn>ans&&c>=b&&b>=a)//因为b从1开始,但b<a没有意义{minn=ans;X=a,Y=b,Z=c;}}printf("%d\n%d %d %d\n",minn,X,Y,Z);}return 0;
}
这篇关于Three Integers(暴力,行走在TLE的边缘)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!