Description
求一个给定的圆(x^2+y^2=r^2),在圆周上有多少个点的坐标是整数。
Input
只有一个正整数n,n<=2000 000 000
Output
整点个数
Sample Input
4
Sample Output
4
解法:
一道极其经典的题……
还有一个极其经典的题解。
不过先说两句我的想法:由于数据范围比较大,所以显然不能直接从1到r枚举x之类。于是我们就需要想到一个更好的枚举坐标的办法。
这样我们就想到了一个奇怪的推导 使得我们缩小了需要枚举的范围。
具体的过程看这个博客就好啦!
http://blog.csdn.net/csyzcyj/article/details/10044629
不过几个需要注意的地方:他说的d有两种情况,因为他两个情况用的同一个d,我搞混了之后弄了很久才明白。可以自己把第一个d代换成d‘。
两个数互质的话,它们的平方肯定也互质。
然后还有判断一个数是否是完全平方数的神奇方法:
double x=sqrt(n);
floor(x)==x的话n就是完全平方数。
代码
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b)
{
if(a<b)swap(a,b);
return a%b==0?b:gcd(b,a%b);
}
bool check(ll x,double y)
{
if(floor(y)==y)
{
ll y1=(ll)floor(y);
if(gcd(x,y1)==1 && x!=y1) return true;
}
return false;
}
int main()
{
ll r;
scanf("%lld",&r);
ll ans=0;
for(ll d=1;d*d<=2*r;d++)
{
if((2*r)%d==0)
{
for(long long a=1;a<=(long long)sqrt(r/d);a++)
{
double b=sqrt(((2*r)/d)-a*a);
if(check(a,b)) ans++;
}
if(d!=(2*r)/d)
{
for(long long a=1;a<=(long long)sqrt(d/2);a++)
{
double b=sqrt(d-a*a);
if(check(a,b)) ans++;
}
}
}
}
printf("%lld",ans*4+4);
return 0;
}
好啦晚安xD