原题:
求一个给定的圆(x^2+y^2=r^2),在圆周上有多少个点的坐标是整数。
r<=2000 000 000
看题解学数论
首先柿子变形一下
x=√(r-y)(r+y)
令d=gcd(r-y,r+y)
令A=(r-y)/d,B=(r+y)/d
那么x^2=d^2*A*B
由于A和B没有公因数,它俩乘积还是平方数,那么它们只能分别是平方数了
(因为若A不是平方数,则存在次数是基数的质因子,而B又不能有质因子和它拼,所以假设不成立)
gcd的作用就在这,提出公共因子,使平方数的性质出现
继续变柿子
令a^2=A,b^2=B
a^2+b^2=2*r/d
这是另一个关键点,用A+B消去y,这个只能看数学直觉了
然后枚举2*r的所有因子d,再枚举b,检查a是否和b互质即可
注意b^2只需枚举到b*b*2<j或b*b<n/d
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 #define LL long long 8 const double eps=0.0000001; 9 int rd(){int z=0,mk=1; char ch=getchar(); 10 while(ch<'0'||ch>'9'){if(ch=='-')mk=-1; ch=getchar();} 11 while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0'; ch=getchar();} 12 return z*mk; 13 } 14 LL gcd(LL x,LL y){ return (y ? gcd(y,x%y) : x);} 15 LL n; 16 int ans=0; 17 int main(){ 18 cin>>n; LL _2n=sqrt(2.0*n)+eps; 19 if(n==0){ 20 cout<<1<<endl; 21 return 0; 22 } 23 for(LL i=1;i<=_2n;++i)if(!(2*n%i)){ 24 for(LL j=1;j*j*2<i;++j){ 25 LL k=sqrt((i-j*j)*1.0)+eps; 26 if(k*k==i-j*j) 27 ans+=(gcd(k*k,j*j)==1); 28 } 29 for(LL j=1;j*j<n/i;++j){ 30 LL k=sqrt((2*n/i-j*j)*1.0)+eps; 31 if(k*k==2*n/i-j*j) 32 ans+=(gcd(k*k,j*j)==1); 33 } 34 } 35 cout<<ans*4+4<<endl; 36 return 0; 37 }