A Simple Problem
HDU - 4143Input
The first line is an integer T, which is the the number of cases.
Then T line followed each containing an integer n (1<=n <= 10^9).
Output
For each integer n, please print output the x in a single line, if x does not exit , print -1 instead.
Sample Input
2
2
3
Sample Output
-1
1
Not a simple problem……事情并没有想象中那么简单……
先贴一下AC代码
#include<stdio.h>
#include<math.h>
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
int i;
int minn=999999999,flag=0;
for(i=1;i<sqrt(n);i++)
{
if(n%i==0&&(i+n/i)%2==0&&(n/i-i)%2==0&&i!=n/i&&(n/i-i)>0)
{
flag=1;
if(n/i-i<minn)minn=n/i-i;
}
}
if(flag) printf("%d\n",minn/2);
else printf("-1\n");
}
return 0;
}
y^2=n+x^2->n=y^2-x^2->n=(y+x)(y-x)
因此只要找到n的因子a1,a2,并要求a1,a2满足以下几点:
1.(a1+a2)%2==0;(2y%2==0)
2.a2>a1;(x>0)
3.(a2-a1)%2==0;(2x%2==0)
找到a2-a1的最小值,即为2x,这里效率更高的应该从sqrt(n)开始往下找因子,这里找到的第一对因子就是(a2-a1)最小的了,从小往大数效率应该会低很多。
如果找不到满足这些条件的因子,那当然就输出-1。
————————————
这里有一个隐藏的坑,导致我WA好久不过,就是a2和a1的差值,如果一开始把minn设成99999999,将会WA。
贴一下WA代码
#include<stdio.h>
#include<math.h>
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
int i;
int minn=99999999,flag=0;
for(i=1;i<sqrt(n);i++)
{
if(n%i==0&&(i+n/i)%2==0&&(n/i-i)%2==0&&i!=n/i&&(n/i-i)>0)
{
flag=1;
if(n/i-i<minn)minn=n/i-i;
}
}
if(flag) printf("%d\n",minn/2);
else printf("-1\n");
}
return 0;
}
这是为啥??因为n<=1e9,x和y不一定小于1e9,(a2-a1)即2x也不一定小于99999999了……
结果如下
可以看到两者的分歧就在999999996上了,因为这里x=83333330,2x>99999999
————————————
还有一个我自己的问题,关于判断n/i是不是整数……
当然正常的方法是n%i==0,可我非要作死,写了个(double)(n/i)==(int)(n/i),结果可想而知,因为double的精度不够,这样只是近似相等而已,有1e-100的误差也不算相等……导致求n=1e9的时候结果是119(正确答案是375),因为x=119的时候n/i已经很接近整数了。
提醒一下自己不要随便作死,老老实实%%%