zoukankan      html  css  js  c++  java
  • UVA106

    假设x为奇数,y为偶数,则z为奇数,2z与2x的最大公因数为2,2z和2x可分别写作

    • 2z = (z + x) + (z - x)
    • 2x = (z + x) - (z - x)

    那么跟据最大公因数性质,z + x和z - x的最大公因数也为2,又因为:

    • (z + x)(z - x) = y2,两边同除以4得:
      ((z + x) / 2)((z - x) / 2) = (y / 2)2

    故可令:

    • z + x = 2m2, z - x = 2n2
      其中z = m + n, x = m - n(m与n互质)

    则有:

    • y2 = z2 - x2 = 2m22n2 = 4m2n2
      即y = 2mn。

    综上所述,可得到下式:

    • x = m2 - n2, y = 2mn, z = m2 + n2. (m, n为任意自然数)

    这里还有一个问题:题目要求统计(x, y, z)三元组的数量时只统计x,y和z两两互质的的情况,这个问题用上面的算法就可以解决了。但对于统计p的数量,题目并不限定三元组是两两互质的。但是上式不能生成所有x, y, z并不是两两互质的情况。然而假设x与y最大公因数w不为1,则z也必能被w整除,因此w为x, y, z三个数的公因数。归纳总结可知,所有非两两互质的x0, y0, z0都可由一组互质的x, y, z乘以系数得到。根据以上理论就可以快速的求解了。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cmath>
     4 #include<algorithm>
     5 #define MAX 1000010
     6 using namespace std;
     7 bool vis[MAX];
     8 int prime[MAX][3],n;
     9 int gcd(int a, int b)
    10 {
    11     return b == 0 ? a : gcd(b, a%b);
    12 }
    13 int upper(int l, int r, int v)
    14 {
    15     int m;
    16     while (l < r)
    17     {
    18         m = l + (r - l) / 2;
    19         if (prime[m][2] <= v) l = m + 1;
    20         else r = m;
    21     }
    22     return r;
    23 }
    24 int cmp(const void*a, const void*b)
    25 {
    26     return ((int*)a)[2] - ((int*)b)[2];
    27 }
    28 int main()
    29 {
    30     int i,j,z,x,y,k=0;
    31     int imax = int(sqrt(MAX >> 1)+0.5),jmax;
    32     for (i = 1; i <= imax; i++)
    33     {
    34         jmax = int(sqrt(MAX - i*i) + 0.5);
    35         for (j = i + 1; j <= jmax; j++)
    36             if ((i & 1) + (j & 1 )== 1 && gcd(i, j) == 1)//(i&1)+(j&1)==1 一奇一偶
    37             {
    38                 y = 2 * i*j;
    39                 z = i*i + j*j;
    40                 x = j*j - i*i;
    41                 if (x*x+y*y==z*z&&z<=1000000)
    42                 {
    43                     prime[k][0] = x;
    44                     prime[k][1] = y;
    45                     prime[k++][2] = z;
    46                 }
    47             }
    48     }
    49     qsort(prime,k,sizeof(prime[0]),cmp);
    50     while (scanf("%d", &n) == 1)
    51     {
    52         int a = upper(0, k, n);
    53         memset(vis, 0, n + 1);
    54         for (i = 0; i < a; i++)
    55             for (j = 1; j*prime[i][2] <= n; j++)
    56             {
    57                 vis[j*prime[i][0]] = 1;
    58                 vis[j*prime[i][1]] = 1;
    59                 vis[j*prime[i][2]] = 1;
    60             }
    61         int count = 0;
    62         for (i = 1; i <= n; i++)
    63             if (!vis[i]) count++;
    64         printf("%d %d
    ", a, count);
    65     }
    66     return 0;
    67 }
    View Code
  • 相关阅读:
    [leetcode]Insert Interval @ Python
    [leetcode]Merge Intervals @ Python
    [leetcode]Maximum Subarray @ Python
    [leetcode]Jump Game II @ Python
    [leetcode]Jump Game @ Python
    [leetcode]Wildcard Matching @ Python
    tomcat 配置https 外部链接显示证书不安全 原因找到为其他地方的链接用的ip地址,证书是发给域名的所以报错
    netstat -tanp ss -lntup |grep
    https://www.pstips.net/ powershell
    awk之getline()函数运用
  • 原文地址:https://www.cnblogs.com/cdyboke/p/4849428.html
Copyright © 2011-2022 走看看