勾股數組咱們都很熟悉,給一個勾股數組同乘一個整數獲得的還是勾股數組,但咱們對它並不感興趣,今天咱們只研究它的本原形式(固然是在正整數範圍內)。數組
本原勾股數組(PPT)是一個知足 $ a^{2}+b^{2}=c^{2} $ 的三元組 $ (a,b,c) $ ,且 \(a,b,c\) 互素(除1外沒有其餘公因數)。
例如:$ (3,4,5) (5,12,13) (15,8,17) (7,24,25) (21,20,29) (35,12,37) (9,40,41) $spa
觀察這些例子,咱們容易獲得一些結論。例如,code
性質1.(1) 本原勾股數組 $ (a,b,c) $ 中, \(a\)與\(b\)奇偶性不一樣,而且\(c\)爲奇數。get
這是正確的,證實以下(分類討論):string
若 \(a,b\) 均爲偶數,那麼\(c\)也爲偶數,則此勾股數組不是本原的,排除;
若 \(a,b\) 均爲奇數,那麼\(c\)爲偶數,則必存在正整數 \(x,y,z\) 使得 $ a=2x+1, b=2y+1, c=2z$ ,因而有io
因爲兩邊奇偶性不一樣,故等式不成立;
所以\(a,b\)奇偶性不一樣,由此\(c\)爲奇數(方便起見,咱們約定,如無特殊說明,下文中\(a\)爲奇數,\(b\)爲偶數)
table
有了這個性質之後,咱們就能夠開始考慮求解一個問題:如何求出全部的本原勾股數組?換句話說,如何表示出方程\(a^{2}+b^{2}=c^{2}\)(\(a\)爲奇數,\(b\)爲偶數,且\(a,b,c\)互素)的全部正整數解?class
先寫出結論:gc
(勾股數組定理)每一個本原勾股數組(a,b,c)(a爲奇數,b爲偶數)都可以由下面的公式給出
方法\(a=st,b=\frac{(s^{2}-t^{2})}{2},c=\frac{(s^{2}+t^{2})}{2}\)
其中 \(s>t\geq1,s,t\) 互素且均爲奇數
下面,咱們將使用因式分解與整除性證實這必定理。
首先移項並進行因式分解:\(a^{2}=(c+b)(c-b)\)
而後……就沒有思路了 o(╯□╰)o 別急,咱們先列個表看看這個式子有什麼性質:
咱們發現,貌似..... \(c+b\) 與 \(c-b\) 都是徹底平方數誒,並且 \(c+b\) 與 \(c-b\) 好像是互素的。等等, \(c+b\) 與 \(c-b\) 的積\(a^{2}\)是徹底平方數,假設 \(c+b\) 與 \(c-b\) 互素,那麼由惟一分解定理,就能夠推出 \(c+b\) 與 \(c-b\) 都是徹底平方數(這是顯然的,由於 \(c+b\) 與 \(c-b\) 分解到的素數徹底不一樣)。因而接下來證實 \(c+b\) 與 \(c-b\) 互素:設整數d整除 \(c+b\) 與 \(c-b\) (即\(d\)爲 \(c+b\) 與 \(c-b\) 的公因數),那麼\(d\)也整除
又 \(b\) 與 \(c\) 互素,那麼\(d\)只能等於1或2。又\(d\)整除\(c-b\)(奇數),那麼\(d\)只能等於1(或者也能夠由\(d\)整除 \((c-b)(c+b)=a^{2}\) 且\(a\)爲奇數推出)。因而 \(c+b\) 與 \(c-b\) 的公因數只有1(也即互素),便可獲得 \(c+b\) 與 \(c-b\) 均爲徹底平方數,因而有:
其中\(s>t≥1\),\(s,t\)互素且均爲奇數(這樣才能知足 \(c+b\) 與 \(c-b\) 的其它性質)
關於\(c\)與\(b\)解方程,並代入求\(a\)獲得
那麼,這個定理有什麼用呢?固然就是打表列舉本原勾股數組了,代碼以下:
int gcd(int a,int b){ //求a,b的最大公因數 return b==0?a:gcd(b,a%b); } void ppt_table(int n){ //打印全部c不超過n的本原勾股數組 int a,b,c; int maxs=(int)sqrt(2*n); //s的上界 for(int s=2;s<=maxs;s++) for(int t=1;t<s;t++) if(s%2 && t%2 && gcd(s,t)==1){ a=s*t; b=(s*s-t*t)/2; c=(s*s+t*t)/2; if(c<=n) printf("%d %d %d",a,b,c); } }
例題(這個知識點的題幾乎沒有,事實上我只找到這一個):
洛谷 UVA106 費馬vs畢達哥拉斯
題意:給定\(N\),求:1.知足\(c≤N\)的本原勾股數組的個數;2.知足\(c≤N\)的勾股數組(不必定本原)都不包含的正整數 \(p(0<p≤N)\) 的個數。
分析:使用勾股數組定理,將上面的代碼稍稍更改一下便可。
#include <cstdio> #include <cmath> #include <cstring> using namespace std; const int N=1e6+5; int vis[N],cnt,ans; int gcd(int a,int b){ return b==0?a:gcd(b,a%b); } void solve(int n){ int a,b,c; int maxs=(int)sqrt(2*n); for(int s=2;s<=maxs;s++) for(int t=1;t<s;t++) if(s%2 && t%2 && gcd(s,t)==1){ a=s*t; b=(s*s-t*t)/2; c=(s*s+t*t)/2; if(c<=n) cnt++; for(int k=1;k*c<=n;k++) vis[k*a]=vis[k*b]=vis[k*c]=1; } } int main(){ int n; while(scanf("%d",&n)==1){ solve(n); for(int i=1;i<=n;i++) if(!vis[i]) ans++; printf("%d %d\n",cnt,ans); memset(vis,0,sizeof(vis)); cnt=ans=0; } return 0; }
有沒有注意到第一個性質的序號是「1.(1)」?沒錯,這樣相似的性質還有兩條,證實方法是相似的:
性質1.(2) 本原勾股數組 $ (a,b,c) $ 中, \(a\) 與 \(b\) 有且僅有一個是\(3\)的倍數,而且\(c\)不是\(3\)的倍數。
性質1.(3) 本原勾股數組 $ (a,b,c) $ 中, \(a,b,c\) 中有且僅有一個是\(5\)的倍數。
證實方法與性質1.(1)徹底相似,分類討論並一一排除便可。值得一提的是,在證實 \(a,b,c\) 不可能都不是\(5\)的倍數時,會發現諸多狀況中,左式模\(5\)的值老是\(0,2,3\),而右式的老是\(1,4\),因而這一狀況不成立。
另外,由勾股數組定理也能夠推出幾條有趣的性質:
性質2. 本原勾股數組 $ (a,b,c) $ 中, 若 \(s-t=2\),則 \(c-a=2\)。
性質3. 本原勾股數組 $ (a,b,c) $ 中, \(2(c-a)\) 是徹底平方數。
證實:由勾股數組定理,\(2(c-a)=s^{2}+t^{2}-2st=(s-t)^{2}=4\),故 \(s-t=2\).
用 \(c^{2}\) 除方程 $ a^{2}+b^{2}=c^{2} $ 獲得
所以,有理數對 \((a/c,b/c)\) 是方程 \(x^{2}+y^{2}=1\) 的解。
令 \(u=\frac{s+t}{2},v=\frac{s-t}{2}\) ,
由勾股數組定理獲得, \((a,b,c)=(u^{2}-v^{2},2uv,u^{2}+v^{2})\)
同除以 \(u^{2}+v^{2}\) ,獲得 \((\frac{u^{2}-v^{2}}{u^{2}+v^{2}},\frac{2uv}{u^{2}+v^{2}},1)\)
令 \(m=u/v\),因而有 \((a,b)=(\frac{1-m^{2}}{1+m^{2}},\frac{2m}{1+m^{2}})\) ,這即是能夠給出單位圓上全部有理點的定理:
定理:圓 \(x^{2}+y^{2}=1\) 上的全部座標爲有理數的點均可以由公式
\((x,y)=(\frac{1-m^{2}}{1+m^{2}},\frac{2m}{1+m^{2}})\)
獲得,其中\(m\)取有理數值。(點 \((-1,0)\) 除外,這是當 \(m\to\infty\) 的極限值)
事實上,上述推理並不嚴謹,這個定理嚴格一些的證實須要從過點 \((-1,0)\) 的直線及其斜率出發,各位看官如果有興趣可自行完成證實。
End.