将整数拆分为勾股数的问题解决

来源:互联网 发布:ubuntu wine 卸载软件 编辑:程序博客网 时间:2024/05/20 18:03

在群里看到这样一个问题:


解法如下:

 

#include <stdio.h>#define MAX 500000unsigned g_array[MAX + 1] = {0};#define EVEN(x) (((x)&1)==0)#define ODD(x)  (((x)&1)==1)//判断两个数字是否互质的标准算法unsigned __int64 gcd(unsigned __int64 a, unsigned __int64 b) /* Non-recursive version */ {    unsigned __int64 ret=1;    unsigned __int64 t =0;L:    if(a==b || b==0 ) return ret*a;    if( b==1 ) return ret;    if( a<b) {        t = a;         a = b;         b = t;         goto L;    }    if( EVEN(a) ) {        a >>= 1;         if( EVEN(b) ) {     /* 2*gcd(a>>1, b>>1) */            b >>= 1;             ret <<= 1;         }             /* gcd(a>>1, b) */        else {}    }    else {        if( ODD(b) ) {    /* gcd( (a-b)/2, b) */            a -= b;             a >>= 1;          }        else {        /* gcd(a, b>>1) */            b >>=1;         }    }    goto L;}//填充全局数组内容void GetArray(){    unsigned __int64 x;    unsigned __int64 y;    unsigned __int64 a;     //直角边长度    unsigned __int64 b;     //另一条直角边长度    unsigned __int64 c;     //斜边长度    unsigned __int64 t;     //三边总长度    for (x = 1; ; x += 1)    {        //令y的值为最小(为x+1),用勾股数公式求出三边长度        a = x * (x + 1) * 2;        b = (x + 1) * (x + 1) - x * x;        c = (x + 1) * (x + 1) + x * x;        //判断是否可以提前结束循环        if (a + b + c > MAX)        {            break;        }        //枚举y,总长度大于MAX时跳出循环        for (y = x + 1; y * (x + y) * 2 <= MAX; y += 1)        {            //用勾股数公式求出三边长度            a = y * x * 2;            b = y * y - x * x;            c = y * y + x * x;            //保证三边互质            if (gcd(gcd(a, b), c) == 1)            {                t = a + b + c;                //标识所有此总长度的倍数的地方拆分方案数加一                while (t <= MAX)                {                    g_array[t] += 1;                    t += (a + b + c);                }            }        }    }}int main(){    //获取所有数字的解法数    GetArray();    //求出其中解法数为一的个数    int nCount = 0;    for (int n = 0; n <= MAX; n += 1)    {        if (g_array[n] == 1)        {            nCount += 1;        }    }    printf("%d\n", nCount);    return 0;}

答案是54446种
原创粉丝点击