擴展歐幾裏得與二元不定方程
阿新 • • 發佈:2018-03-02
歐幾裏得 註意 自己 需要 pan ret 括號 AC 得到
二元不定方程,就是形同ax+by=c的二元方程,
只不過有無數組解罷了。
還有原諒我蒟蒻,不會用字母的寫法,只好直覺+小學數學寫法了
我們可以使用輾轉相除法來解決(過渡好生硬啊)
我們首先來看一組例子
為了方便理解,特將每個多項式系數都寫了出來,同時並沒有將符號帶進括號
37x-107y=25
37x-(37*2+33)y=25
37(x-2y)-33y=25
(-33*-1+4)(x-2y)-33y=25
-33(-x+3y)+4(x-2y)=25
(4*-8-1)(-x+3y)+4(x-2y)=25
4(9x-26y)-1(-x+3y)=25
(-1*4+0)(9x-26y)-(-x+3y )=25
-(-37x+107y)+0(9x-26y)=25
我們自下而上看
因為系數0的存在
那麽9x-26y=0
我們又可以驚奇的發現
9x-26y正好在它上面式子中出現了。
考慮整體思想,將括號內的多項式(就是(x-+3y))(or單項式)看做一個整體,便可求得(-x+3y)的值(當做一次方程來做)
再如此處理,便可將x,y的一對特值找出來
那怎麽求出其他的特值捏?
對於一個減法,我們總可以用正號將一個減數變成加數
那麽就變成了兩個數和相等的情況(真啰嗦)
那麽我們這一個整數d
ax+by=c=a(x+bd)+b(y+ad)=c
因為將括號開出來時就將bd 和 ad消去了,所以兩數的和不會改變
所以(x+bd)與 (y-ad)也是一組特解
這樣有條件枚舉d便會找到想要的特解
在理解了如何利用輾轉相除法來求解後,再來看程序實現
#include<iostream>
using namespace std;
void exgcd(long long a,long long b,long long &x,long long &y,long long r)
{
if(b==0)//有了系數0,為什麽0肯定在b上?請回看gcd
{
x=r/a; //最終結果有可能系數為非零整數
y=0;//e.....
return ;
}
exgcd(b,a%b,x,y,r);//輾轉相除
//因為這裏是回溯,註意下面寫下一層就是遞歸意義上的下一層。可能理解起來有些別扭,原諒我吧233.
long long k=x;//暫時保留下一層的x,註意是自下而上計算的
x=y;//可以參考例子,例子我覺得自己寫的很公正(就是有些別扭)
y=k-a/b*y;//k是下一層的x,下一層的x是這一層的x-這一層的x,y的系數的商*這一層的x+這一層的y(不乘任何數)(這裏的y是變量,儲存的是下一層的x),便得到了這一層的y。
return ;
}
int main()
{
long long a,b,l;//ab為xy的系數,l為化成ax+by=c後的c
cin>>a>>b>>l;
long long x,y;
exgcd(a,b,x,y,l); //擴展歐幾裏得是特殊的二元不等式
cout<<x<<" "<<y;
}
擴歐只需要將ax+by=c中的c變為1即可
擴展歐幾裏得與二元不定方程