本章主要讨论的是本原勾股数组,也就是关于满足
a2+b2=c2
的三元组
(a,b,c)
,且
(a,b,c)
互质的问题。
这章中提到一个概念:本原勾股数组(PPT)是一个三元组
(a,b,c)
,其中
a,b,c
没有公因子,且满足
a2+b2=c2
,就是
gcd(a,b,c)=1
。
对于本原勾股数组,显然
a
和
那么我们最关心的是如何求出所有的本原勾股数组。
如果将公式转化一下,得到
(反证法)证明:
如果
d|(c+b)且d|(c−b)
,那么显然有
d|((c+b)+(c−b))
和
d|((c+b)−(c−b))
即
d|2b且d|2c
,因为在定义本原勾股数组的时候已经有了
b
和
因此,如果将
a2
进行质因数分解,那么会有
a=pa11∗pa22∗pa33...pann
,其中指数
a1,a2,a3...an
为偶数(因为这样才能保证
a2
开根号后为整数),又因为
c+b
和
c−b
没有公因数,
c+b
和
c−b
各用
a
分解后的必然是
本原勾股数公式:a=m²−n²,b=2mn,c=m²+n² 一些构造题和数论题会涉及:本原勾股数组。
例题:
http://codeforces.com/contest/707/problem/C
http://acm.hdu.edu.cn/showproblem.php?pid=3422
http://poj.org/problem?id=1305
习题解析:
(a) 反证法。假设
a
和b 都不是3的倍数,那么由于
a
和b 的奇偶性不同,因此我想的方法是分成4种情况讨论:
由于a和b具有互换性,因此假定
a
为奇数,b 为偶数。
-
amod3=1,bmod3=1
那么
a=6x+1,b=6y+4,
那么根据勾股定理,可以得到
c=6z+5
的形式,再代入
a2+b2=c2
后可得:
36x2+12x+1+36y2+48y+16=36z2+60z+25
整理后可得
3∗(12x2+4x+12y2+16y−12z2−20z)=8
。
3
不是8 的因子,所以显然不存在整数
x,y
使得该式成立。 -
amod3=1,bmod3=2
那么有
a=6x+1,b=6y+2,
那么可以得到
c=6y+5
的形式,代入
a2+b2=c2
后可得
36x2+12x+1+26y2+24y+4=26y2+60z+25
整理后常数项
20
也不是
3
的因子,所以不存在整数x,y - 同理,可证明当
amod3=2,bmod3=1
和
amod3=2,bmod3=2
中同样找不到
x,y
成立,因此假设不成立,所以证明了
a
或者
b 必定是
3
的倍数。
(b)根据上面的反证法也可以证明a 或
b
或c 是
5
的倍数。
证明:如果d|m 和
d|n
,则
d|(m−n)且d|(m+n)
的证明。
很显然有
m=ad,n=bd,
则
m−n=d(a−b),m+n=d(a+b),
显然能够被
d
整除。
证明略。奇数和4的倍数可以出现在本原勾股数组中,而形如4n+2的偶数不可能出现在本原勾股数组中。
定理:如果x 和
y
没有公约数,那么x2+y2 的任何奇素因子 都必定形如
4n+1
.
显然是存在相同
c
值的2 个本原勾股数组的。自己打个表就知道了。也可以找到相同
c
值的4 个本原勾股数组。但找不到
3个
(10,000,000内),可以找到
4
个的,找不到5 个的,也找不到
6
个的。。。
测试代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n;
ll vis[10000000+7];
ll gcd(ll a,ll b){
return b==0?a:gcd(b,a%b);
}
ll cot[100000000+7];
int main()
{
while(~scanf("%lld",&n))// <= 1,000,0000
{
memset(vis,0,sizeof(vis));
int m=sqrt((double)n);
ll ans=0;
ll x,y,z;
ll a,b,d;
for(ll i=1;i<=m;i+=2)
{
for(ll j=2;j<=m;j+=2)
{
a=max(i,j);
b=min(i,j);
d=gcd(a,b);
if(d==1)
{
x=a*a-b*b;
y=2*a*b;
z=a*a+b*b;
cot[z]++;
for(int k=1;k*z<=n;k++)
{
vis[x*k]=1;
vis[y*k]=1;
vis[z*k]=1;
}
if(z<=n)
ans++;
}
}
}
printf("有%lld个本原勾股数组\n",ans);
ans = 0;
for(int i=1;i<=n;i++){
ans=max(ans,cot[i]);
if(ans==2)cout<<"存在2个."<<endl;
// if(ans==4)cout<<"存在4个"<<endl;
// if(ans==5)cout<<"存在5个"<<endl;
//if(ans==6)cout<<"存在6个"<<endl;
}
cout<<"(最大值)相同的有"<<ans<<"个."<<endl;
}
return 0;
}
(a) 反证法。假设
a
和
由于a和b具有互换性,因此假定
a
为奇数,
-
amod3=1,bmod3=1
那么 a=6x+1,b=6y+4, 那么根据勾股定理,可以得到 c=6z+5 的形式,再代入 a2+b2=c2 后可得:
36x2+12x+1+36y2+48y+16=36z2+60z+25
整理后可得 3∗(12x2+4x+12y2+16y−12z2−20z)=8 。
3 不是8 的因子,所以显然不存在整数 x,y 使得该式成立。 -
amod3=1,bmod3=2
那么有 a=6x+1,b=6y+2, 那么可以得到 c=6y+5 的形式,代入 a2+b2=c2 后可得
36x2+12x+1+26y2+24y+4=26y2+60z+25
整理后常数项 20 也不是 3 的因子,所以不存在整数x,y - 同理,可证明当
amod3=2,bmod3=1
和
amod3=2,bmod3=2
中同样找不到
x,y
成立,因此假设不成立,所以证明了
a
或者
b 必定是 3 的倍数。
(b)根据上面的反证法也可以证明a 或 b 或c 是 5 的倍数。
证明:如果
很显然有
m=ad,n=bd,
则
m−n=d(a−b),m+n=d(a+b),
显然能够被
d
整除。
证明略。奇数和4的倍数可以出现在本原勾股数组中,而形如4n+2的偶数不可能出现在本原勾股数组中。
定理:如果
显然是存在相同
c
值的
测试代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n;
ll vis[10000000+7];
ll gcd(ll a,ll b){
return b==0?a:gcd(b,a%b);
}
ll cot[100000000+7];
int main()
{
while(~scanf("%lld",&n))// <= 1,000,0000
{
memset(vis,0,sizeof(vis));
int m=sqrt((double)n);
ll ans=0;
ll x,y,z;
ll a,b,d;
for(ll i=1;i<=m;i+=2)
{
for(ll j=2;j<=m;j+=2)
{
a=max(i,j);
b=min(i,j);
d=gcd(a,b);
if(d==1)
{
x=a*a-b*b;
y=2*a*b;
z=a*a+b*b;
cot[z]++;
for(int k=1;k*z<=n;k++)
{
vis[x*k]=1;
vis[y*k]=1;
vis[z*k]=1;
}
if(z<=n)
ans++;
}
}
}
printf("有%lld个本原勾股数组\n",ans);
ans = 0;
for(int i=1;i<=n;i++){
ans=max(ans,cot[i]);
if(ans==2)cout<<"存在2个."<<endl;
// if(ans==4)cout<<"存在4个"<<endl;
// if(ans==5)cout<<"存在5个"<<endl;
//if(ans==6)cout<<"存在6个"<<endl;
}
cout<<"(最大值)相同的有"<<ans<<"个."<<endl;
}
return 0;
}
对于问题
(a)
:
首先,
b=4T1:(3,4,5)
b=4T2:(5,12,13)
b=4T3:(7,24,25)
b=4T4:(9,40,41)
观察可以找到规律:一个数是奇数,第二个数是
Tn
,第三个数是
(Tn)+1
。即:
a=2k+1,b=2k(k+1),c=2k(k+1)+1
,即
a=2k+1,b=2k2+2k,c=2k2+2k+1
.
对于问题
(b)
,由
(a)
可以得到,
b
显然是是三角数的
(6) 对于 (a)(b)(c) ,由上面的题目我们可以得到: a=4k,b=4k2−1,c=4k2+1 ,即: c=a+2 。那么: a=4k,b=4k2−1,c=4k2+1 就是通用公式。
(7) 你打个表或者套上面的公式,可以发现,打表发现 2c−2a 为完全平方数。特殊形式: 2c−2a=2∗((s2+t2)2−st)=(s−t)2 。
(8) 自行阅读与了解。