原题:http://tz.ahalei.com/problems/view/58
这道题去年7月14日第一次解出。一开始真是毫无头绪,然后百度相关资料,好不容易找到点结论了,但描述不清,我就想找一本系统的书看看,看到别人说跟《数论》有关,我就去找陈景润的《初等数论I》,没想到真找到结论了。也是这次,让我深感理论学习的重要性,所以接下来的暑假我把那本《初等数论I》看了一遍,也有去做部分习题。
回到该题,见下面这个结论:
这个结论的意思是,我们可以通过遍历有特定关系、约束的a,b,直接构造出勾股数x,y,z。上图中,用(x,y)、(a,b)括起的内容代表计算它们的最大公约数。简单的推导,就能推出周长L=2a(a+b)。今天又把程序敲了一遍,一直忽略了a+b不能为偶数、a和b的最大公约数为1的限制条件,错了几次。最后,注意这个公式算的都是基本解(三条边长的最大公约数为1),如(3,4,5),我们要把它所有的倍数再加进来,如(6,8,10),(9,12,15)……。
“mymath.h”:http://blog.csdn.net/code4101/article/details/17993747
“debug.h”:http://blog.csdn.net/code4101/article/details/17993293
要在函数内开辟大数组,祥见此篇博客:http://blog.csdn.net/code4101/article/details/18444377,定义成全局变量则不会有该问题。
#include <iostream>
#include "mymath.h"
#include "debug.h"
using namespace std;
const int max_L = 1500000;
int main()
{
tic;
int ans = 0, a, b, L, t, i;
int mark[max_L+1]={0}; // 这题改成char数组也不会错,保险还是以int为妙
for(a=2; a<=sqrt(max_L/2.0); a++) // a的上界可以用周长公式推出
{
for(b=a-1; b>0; b-=2) // 注意更新操作是b-=2,(a+b)不能为偶数
{
if(gcd(a,b)==1) // 注意还有这句话
{
L = 2*a*(a+b); // 算出基本解的周长
for(t=L; t<=max_L; t+=L)
mark[t]++; // 周长L的所有倍数都能构造出直角三角形
}
}
}
for(i=1; i<=max_L; i++)
if(mark[i]==1) ans++; // 统计只有一种构造方法的周长个数
cout << "用时"; toc;
cout << "ans = " << ans << endl;
return 0;
}