BZOJ 1041: [HAOI2008]圆上的整点
1041: [HAOI2008]圆上的整点
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 4547 Solved: 2042
[Submit][Status][Discuss]
Description
求一个给定的圆(x^2+y^2=r^2),在圆周上有多少个点的坐标是整数。
Input
只有一个正整数n,n<=2000 000 000
Output
整点个数
Sample Input
4
Sample Output
4
HINT
题解
x*x+y*y=r*r
y=sqrt((r-x)*(r+x))
设i=gcd(r-x,r+x),设A=(r-x)/i,B=(r+x)/i,显然gcd(A,B)=1。
那么y*y=i*i*A*B,因为A!=B,所以A和B一定都是平方数,设a=sqrt(A),b=sqrt(B),那么a*a+b*b=2*r/i。
那么枚举i,再枚举a,计算出b,再判断gcd(A,B)是否为1。
求出第一象限的点数都,ans=ans*4+4,因为坐标轴上有4个点。
代码
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<iostream> #define LL long long using namespace std; LL r,ans; LL gcd(LL x,LL y){ if(!y)return x; return gcd(y,x%y); } bool check(LL x,LL y){ if(gcd(x*x,y*y)==1&&x!=y)return true; return false; } int main(){ scanf("%lld",&r); double k; for(LL i=1;i<=sqrt(2*r);i++){ if((2*r)%i==0){ for(LL j=1;j<=sqrt(r/i);j++){ k=sqrt(2*r/i-j*j); if(k==floor(k))if(check(j,floor(k)))ans++; } if(2*r/i!=i){ for(LL j=1;j<=sqrt(i/2);j++){ k=sqrt(i-j*j); if(k==floor(k))if(check(j,floor(k)))ans++; } } } } printf("%lld\n",ans*4+4); return 0; }