UVa 106 - Fermat vs. Pythagoras

来源:互联网 发布:医疗器械软件变更注册 编辑:程序博客网 时间:2024/05/16 11:41

对于a2+b2=c2,求出所有满足条件的(a,b,c)三元组,输出a,b,c三个互质的组别的数量和从1到N中所有
的三元组中都没有出现过的数字的个数。

互质毕达哥拉斯三元组,可直接得到:

a = m^2-n^2    b = 2mn    c = m^2+n^2

因为三个变量之间两两互质,所以a,b中必为一奇一偶。(详细证明见:http://www.cnblogs.com/devymex/archive/2010/08/07/1799713.html)

因此问题的复杂度就可以降为O(m*n),即:最坏1000*1000。

除互质勾股数外,其他所有勾股数三元组都可以由求出的互质勾股数乘以一定的系数得到,由此可以得到三元组没出现的数字的个数(n - 所有勾股数个数)。

代码如下:

#include <cstdio>#include <cmath>#include <cstring>const int MAXN = 1000001;bool vis[MAXN];int gcd(int m, int n){    int k = m%n;    while(k)    {        m = n;        n = k;        k = m%n;    }    return n;}int main(){#ifdef test    freopen("sample.txt", "r", stdin);#endif    int n;    while(scanf("%d", &n) != EOF)    {        int a, b, c, sancct = 0, notsanct = n;        int sqrtn = (int)sqrt((double)n);        memset(vis, false, sizeof(vis[0])*(n+1));        for(int i = 1; i <= sqrtn; ++i)        {            for(int j = i+1; j <= sqrtn; j+=2)            {                if(gcd(i,j) == 1)                {                    a = j*j-i*i;                    b = 2*i*j;                    c = j*j+i*i;                    if(c>n)                        break;                    ++sancct;                    int nc = n/c;                    for(int k = 1; k<=nc; ++k)                    {                        vis[k*a]=true;                        vis[k*b]=true;                        vis[k*c]=true;                    }                }            }        }        for(int i = 1; i <= n; ++i)            notsanct -= vis[i];        printf("%d %d\n", sancct, notsanct);    }}


原创粉丝点击