[HDU4143] A Simple Problem

题目

原题地址

解说

显然数学题。
因为\(y^2=n+x^2\),所以移一下项可以得到\(y^2-x^2=n\),即\((y+x)(y-x)=n\),这样就很显然了,我们把\(n\)分解为\(a,b\),只要满足\(a=y+x,b=y-x\),即\(a+b=2y,a-b=2x\),即\(a-b\)是偶数即可,\(x\)就等于\((a-b)/2\)
如果我们直接从\(1\)开始分解质因数的话,显然时间效率是\(O(\sqrt n)\),这个效率似乎不能再优化了,但是用一个小技巧可以让它稍微快一些。我们要找的是最小的\(x\),即我们想让\(a,b\)最接近,那么我们就不应该改从\(1\)开始循环,而应该从\(\sqrt n\)开始,这样我们找到的第一组符合条件的\(a,b\)就一定是差最小的,这时候直接\(break\)就行了,没必要再继续下面的循环了。
另外注意一点,题目中说了\(positive \ integer \ x\),即\(x\)是个正数,那么\(n\)是完全平方数的话输出\(0\)就错了(这个点卡了我一节课)

代码

#include
using namespace std;
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n;bool flag=0;
		scanf("%d",&n);
		for(int i=sqrt(n);i>=1;i--){
			if(n%i==0){
				int b=n/i;
				if(b==i) continue;
				if((b-i)%2==0){
					printf("%d\n",(b-i)/2);
					flag=1;
					break;
				}
			}
		}
		if(!flag) printf("-1\n");
	}
	return 0;
}

尾声:关于gyz大佬代码冗余部分的评论

最开始确实没发现\(x\)是正数这么回事,于是找来了\(gyz\)大佬的代码对拍,才发现了这个错,但是反观他的代码有许多冗余部分,很不优美,也不简洁,极大地影响了阅读体验,下面进行简短评论。

#include
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		int n,res=-1;
		scanf("%d",&n);
		for(int i=1;i*i(a-i>>1))res=a-i>>1;//这里不用判断,毕竟以1到根号n的顺序找的话x一定是越来越小的
		}
		printf("%d\n",res);
	}
	return 0;
}

(以上仅是个人意见,无意侵犯)
幸甚至哉,歌以咏志。

你可能感兴趣的:([HDU4143] A Simple Problem)