在群里看到这样一个问题:
解法如下:
#include <stdio.h>
#define MAX 500000
unsigned 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种