BZOJ 1041 [HAOI2008]圆上的整点

1041: [HAOI2008]圆上的整点

Description

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

Input

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

Output

  整点个数

Sample Input

4

Sample Output

4
  这么一到水题竟然卡了我一晚上,想起来确实是不可思议。
  样例图示:
  我们可以十分清晰的发现,这似乎就是一道算几题,但我们又很难下手。如果暴力枚举每个整数x,很明显会TLE。那怎么办呢?
  

  右上图可知,我们可以枚举2*d的因数,这是O(sqrt(n)),再去枚举界的个数。因为此处前提为x>0,y>0,所以最后结果为ans*4+4。
  因为涉及实数,所以屡调不顺,下次需多加注意。(floor一个实数结果仍为实数)
  
 1 /************************************************************** 
 2     Problem: 1041 
 3     User: Doggu 
 4     Language: C++ 
 5     Result: Accepted 
 6     Time:104 ms 
 7     Memory:828 kb 
 8 ****************************************************************/
 9   
10 #include <cstdio>  
11 #include <cmath>  
12 long long n, ans;  
13 inline long long gcd(long long a,long long b) {return b==0?a:gcd(b,a%b);}  
14 int main() {  
15     scanf("%lld",&n);  
16     long long cou, b;  
17     double t;  
18     for( long long i = 1; i*i <= 2*n; i++ ) {  
19         if(2*n%i==0) {  
20             cou=i;  
21             for( long long a = 1; 2*a*a < cou; a++ ) {  
22                 t=sqrt(cou-a*a);  
23                 if(t==floor(t)) {  
24                     b=(long long)floor(t);  
25                     if(a!=b&&gcd(a,b)==1) ans++;   
26                 }  
27             }  
28             cou=2*n/i;  
29             if(2*n/i==i) continue;  
30             for( long long a = 1; 2*a*a < cou; a++ ) {  
31                 t=sqrt(cou-a*a);  
32                 if(t==floor(t)) {  
33                     b=(long long)floor(t);  
34                     if(a!=b&&gcd(a,b)==1) ans++;   
35                 }  
36             }  
37         }  
38     }  
39     printf("%lld\n",ans*4+4);  
40     return 0;  
41 }
暴力枚举

 

 
 
posted @ 2017-06-08 21:09  Doggu  阅读(227)  评论(0编辑  收藏  举报