啊哈挑战58: 诡异的直角三角形周长

       原题:http://tz.ahalei.com/problems/view/58

       这道题去年7月14日第一次解出。一开始真是毫无头绪,然后百度相关资料,好不容易找到点结论了,但描述不清,我就想找一本系统的书看看,看到别人说跟《数论》有关,我就去找陈景润的《初等数论I》,没想到真找到结论了。也是这次,让我深感理论学习的重要性,所以接下来的暑假我把那本《初等数论I》看了一遍,也有去做部分习题。

       回到该题,见下面这个结论:

啊哈挑战58: 诡异的直角三角形周长_第1张图片

       这个结论的意思是,我们可以通过遍历有特定关系、约束的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;
}



你可能感兴趣的:(啊哈挑战,勾股数整数解,勾股数生成方法)