神奇的一题,偶对数学的崇拜加深了!
题解: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 }