1041: [HAOI2008]圆上的整点
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4826 Solved: 2198
[ Submit][ Status][ Discuss]
Description
求一个给定的圆(x^2+y^2=r^2),在圆周上有多少个点的坐标是整数。
Input
只有一个正整数n,n<=2000 000 000
Output
整点个数
Sample Input
4
Sample Output
4
题解:
orz。。。
这里先只考虑x,y都大于0的情况
如果x^2+y^2=r^2,则(r-x)(r+x)=y*y
令d=gcd(r-x,r+x),r-x=d*u^2,r+x=d*v^2,显然有gcd(u,v)=1且u<v
有2r=d*(u^2+v^2),y=d*u*v,x=d(v^2-u^2)/2
枚举2r的约数d,再花费sqrt(2r/d)的时间枚举u,求出v=sqrt(2r/d-u^2)然后判断gcd(u,v)=1。
一个数字的平均约数个数为logn个,然后后面那个sqrt(2*r/d)在很多情况下都很小,所以比较快。
最后结果乘以4(四个象限)+4(坐标轴上)即可
代码:
#include<bits/stdc++.h>
using namespace std;
long long ans,n;
long long gcd(long long n,long long m){
if(m==0)return n;
return gcd(m,n%m);
}
void pd(long long x){
long long i,v;
for(i=1;i<=(long long)sqrt(1.0*n/x);i++){
v=(long long)sqrt(1.0*n/x-i*i*1.0);
if(gcd(i,v)==1&&i<=v&&x*(i*i+v*v)==n)ans++;
}
}
int main(){
long long i;
scanf("%lld",&n);
n*=2;
for(i=1;i*i<=n;i++)
if(n%i==0){
if(n/i!=i){
pd(i);
pd(n/i);
}
else pd(i);
}
printf("%lld",ans*4);
}