Shirlies
宁静专注认真的程序媛~

神奇的一题,偶对数学的崇拜加深了!

题解:http://www.algorithmist.com/index.php/UVa_106

我自己再简单的解释一下吧。。。

x2+y2=z2这些都是在x,y,z互质的情况下推的),可以变成:y2=(z - x) * (z + x),我们再变换一下:(y/2)2 = (z - x)/2 * (z +x )/2  ((z-x)/2和(z + x)/2必然为平方数,因为(z - x)/2和(z + x)/2必然是互质,没有共同的因子,自己可以好好想想,推一推) ,设r2 = (z - x)/2,s2 = (z +x )/2,

前面是在互质的情况下退出来的,但是反推的话可能得到的x,y,z不互质

但是推出来的范围更大

这个就无关紧要

因为推出来的是符合x2+y2=z2就行了,能做的就是用倍数补充一下

这题的数据是1000000,但是这样变换后r和s值只需到1000,时间上大大的减少了。。。

具体参考上面的链接

代码如下:
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 
 5 int n;
 6 int pr;
 7 bool f[1000002];
 8 int gcd(int a,int b)
 9 {
10     return  b == 0?a:gcd(b,a%b);
11 }
12 
13 bool tri_gcd(int a,int b,int c)
14 {
15     int ar = gcd(a,b);
16     if(gcd(ar,c) == 1)
17         return true;
18 
19     return false;
20 }
21 
22 void solve()
23 {
24     int m = (int)sqrt(n + 0.5);
25 
26     for(int i = 1;i <= m;i ++)
27     {
28         for(int j = i + 1;j <= m;j ++)
29         {
30             int c = i*i+j*j;
31             if(c > n)
32                 break;
33             int a = j*j-i*i;
34             int b = 2*i*j;
35             if(tri_gcd(a,b,c))
36             {
37                 f[a] = f[b] =f[c] = true;
38                 pr ++;
39                 for(int k = 2;k*c <= n;k ++)
40                 {
41                     f[k*a]= f[k*b] = f[k*c] = true;
42                 }
43             }
44         }
45     }
46 }
47 
48 int main()
49 {
50     while(scanf("%d",&n) == 1)
51     {
52         memset(f,false,sizeof(f));
53         pr = 0;
54         solve();
55         int k =0;
56         for(int i =1;i <=  n;i ++)
57         {
58             if(!f[i])
59                 k ++;
60         }
61         printf("%d %d\n",pr,k);
62     }
63 
64     return 0;
65 }

 

 

posted on 2012-04-14 12:01  Shirlies  阅读(453)  评论(0编辑  收藏  举报