1041: [HAOI2008]圆上的整点

Description

  求一个给定的圆(x^2+y^2=r^2),在圆周上有多少个点的坐标是整数。

Input

  只有一个正整数n,n<=2000 000 000

Output

  整点个数

Sample Input

4

Sample Output

4
 
 
这道题是个喜闻乐见的推公式。。。。
显然枚举每个点是O(r)的。。。会T。。
然后对式子变形。。。
x^2+y^2=r^2→x^2=r^2-y^2=(r+y)(r-y)
我们不妨设d为r+y,r-y的最大公约数。。。则r+y=a^2*d,r-y=b^2*d
然后就可以得到:x^2=d^2*a^2*b^2
为什么是a^2和b^2因为要求x是整数啊,而且d是最大公因数,则a与b互素。。。。
r+y=a^2*d······①
r-y=b^2*d······②
①+②得:2*r=d(a^2+b^2)······③
因为d是r-y的因数,所以1<=d<sqrt(r/2)
如果满足条件,就枚举a,这时有两种情况,因为我们的d是小于sqrt(r/2)的。。。
所以除了d还有可能是2*r/d。。
根据③得到a的取值范围是1<=a^2<(r/d)或1<=a^2*2<d。。。
然后也可以算出b,只需判断b是否是整数并且与a互素就可以了。。。
需要注意的是因为我们算的只是四分之一圆的情况,所以答案要乘4,并且我们没有算x=0或y=0的情况,所以还要加4。。。
然后就解决了。。。
注意:会涉及到精度。。。对于类似x<sqrt(y)的式子可以变成x^2<y提高精度。。。
 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<algorithm>
 7 #include<string>
 8 #include<map>
 9 #include<queue>
10 #include<vector>
11 #include<set>
12 #define inf 1000000000
13 #define maxn 10000+5
14 #define maxm 10000+5
15 #define eps 1e-10
16 #define ll long long
17 #define for0(i,n) for(int i=0;i<=(n);i++)
18 #define for1(i,n) for(int i=1;i<=(n);i++)
19 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
20 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
21 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
22 using namespace std;
23 int read(){
24     int x=0,f=1;char ch=getchar();
25     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
26     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
27     return x*f;
28 }
29 ll gcd(ll a,ll b){if(b==0)return a;return gcd(b,a%b);}
30 int main(){
31     //freopen("input.txt","r",stdin);
32     //freopen("output.txt","w",stdout);
33     ll r=read(),ans=0;
34     for(ll d=1;d*d<=2*r;d++){
35         if((2*r)%d==0){
36             for(ll a=1;a*a<r/d;a++){
37                 double b=sqrt(2*r/d-a*a);
38                 if(b-(ll)b<=eps&&gcd(a,(ll)b)==1)ans++;
39             }
40             for(ll a=1;a*a*2<d;a++){
41                 double b=sqrt(d-a*a);
42                 if(b-(ll)b<=eps&&gcd(a,(ll)b)==1)ans++;
43             }
44         }
45     }
46     printf("%lld",ans*4+4);
47     return 0;
48 }
View Code

 

posted @ 2016-05-18 15:54  HTWX  阅读(133)  评论(0编辑  收藏  举报