# 程序控

IPPP (Institute of Penniless Peasent-Programmer) Fellow

:: :: :: :: :: :: :: ::
 77 随笔 :: 0 文章 :: 442 评论 :: 0 引用

Time limit: 3.000 seconds

## Background背景

Computer generated and assisted proofs and verification occupy a small niche in the realm of Computer Science. The first proof of the four-color problem was completed with the assistance of a computer program and current efforts in verification have succeeded in verifying the translation of high-level code down to the chip level.

This problem deals with computing quantities relating to part of Fermat's Last Theorem: that there are no integer solutions of an + bn = cn for n > 2.

## The Problem问题

Given a positive integer N, you are to write a program that computes two quantities regarding the solution of

x2 + y2 = z2

where x, y, and z are constrained to be positive integers less than or equal to N. You are to compute the number of triples (x,y,z) such that x < y < z, and they are relatively prime, i.e., have no common divisor larger than 1. You are also to compute the number of values 0 < p ≤ N such that p is not part of any triple (not just relatively prime triples).

## The Input输入

The input consists of a sequence of positive integers, one per line. Each integer in the input file will be less than or equal to 1,000,000. Input is terminated by end-of-file.

## The Output输出

For each integer N in the input file print two integers separated by a space. The first integer is the number of relatively prime triples (such that each component of the triple is ≤ N ). The second number is the number of positive integers ≤ N that are not part of any triple whose components are all ≤ N . There should be one output line for each input line.

10
25
100

1 4
4 9
16 27

## Analysis分析

• x = 2a + 1
• y = 2b + 1
• x2 + y2 = (2a + 1)2 + (2b + 1)2
= 4(a2 + b2 + a + b) + 2

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

• (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为任意自然数)

## Solution解答

#include <iostream>
#include <math.h>
using namespace std;
//主函数
int main(void) {
//以下算法的描述详见相关文档
//循环处理所有输入的N，变量i表示N
for (int i, m, n, nMaxM, nMaxN, nCnt = 0; cin >> i; nCnt = 0) {
//aFlags用于标记哪些整数在三元组中出现过
bool aFlags[1000001] = {false};
//循环生成所有的m和n，根据公式，m的最大值必小于N的开平方
for (m = 2, nMaxM = (int)sqrt((float)i - 1); m <= nMaxM; ++m) {
//求出n的最大值，小于等于m，且小于等于i-m^2
nMaxN = (int)sqrt((float)i - m * m);
nMaxN = nMaxN >= m ? m - 1 : nMaxN;
//此时已得到所有可能的m和n的范围，循环生成所有三元组
for (n = 1; n <= nMaxN; ++n) {
//n和m必须互质，忽略都是偶数的情况
if (n % 2 != m % 2) {
//进一步判断互质，辗转相除法求出n和m的最大公因数
int a = m, b = n, c;
for(int r; (r = a % b) != 0; a = b, b = r);
//公因数为1才互质
if (b == 1) {
//生成了一个互质三元组，总数增1
++nCnt;
//根据此三元组，生成所有并不互质的三元组，
a = m * m - n * n, b = 2 * m * n, c = m * m + n * n;
//标记在这些三元组中出现的整数
for (int k = 0; c * k <= i; ++k) {
aFlags[a * k] = aFlags[b * k] = aFlags[c * k] = 1;
}
}
}
}
}
//输出三元组的数量
cout << nCnt << ' ';
//统计并输出没有使用过的整数(p)的数量
for (nCnt = 0, m = 1; m <= i; nCnt += !aFlags[m++]);
cout << nCnt << endl;
}
return 0;
}

posted on 2010-08-14 19:22  Devymex  阅读(...)  评论(...编辑  收藏