cdcq

梦幻小鱼干

导航

【HAOI2008】圆上的整点

原题:

求一个给定的圆(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 }
View Code

 

posted on 2019-08-01 10:27  cdcq  阅读(182)  评论(0编辑  收藏  举报