[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<bits/stdc++.h>
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
",(b-i)/2);
					flag=1;
					break;
				}
			}
		}
		if(!flag) printf("-1
");
	}
	return 0;
}

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

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

#include<cstdio>
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		int n,res=-1;
		scanf("%d",&n);
		for(int i=1;i*i<n;i++){//没有从根号n开始影响时间,但这是思路的问题,无可厚非
			if(n%i)continue;
			int a=n/i;
			if((a+i)%2||(a-i)%2||a-i<0)continue;//首先(a+i)%2,(a-i)%2只判一个就行,因为a-i是偶数a+i一定是偶数
                        //(a-i)<0用不着判断,a一定是大于i的,毕竟i是小于根号n的
			if(res==-1||res>(a-i>>1))res=a-i>>1;//这里不用判断,毕竟以1到根号n的顺序找的话x一定是越来越小的
		}
		printf("%d
",res);
	}
	return 0;
}

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

原文地址:https://www.cnblogs.com/DarthVictor/p/12951450.html