1. 程式人生 > >擴展歐幾裏得與二元不定方程

擴展歐幾裏得與二元不定方程

歐幾裏得 註意 自己 需要 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即可

擴展歐幾裏得與二元不定方程