關於線性同余方程


以前好像提及過關於同余問題,這里就不多講了。。。

現在我要記錄的,好像有些些復雜(當然,只是對於我來說)

 語不驚人死不休!!

首先我要提及的是一次同余方程,形如  ax≡b(mod m)

首先我們要對同余方程ax≡b(mod m) 解的情況進行分析(要的解范圍要在0到m之間,不知道為啥哈哈哈

1.當(a,m)=1時有唯一解;(默默的提一句,最大公約數)

2.當(a,m)| b時有解,解的個數是(a,m)個

 3.當(a,m) 不能整除  b時,無解;

概括一下,也就是說,我們首先要求出a與m的最大公約數,如果是b的倍數,那解的個數就是(a,m),如(a,m)不能整除b,那就是無解!!!

(至於為啥是這樣的,我能力有限,就不在此討論了,也許幾年后的今天我就可以對此完善了)

 

那關於同余方程應該怎樣求解呢?以下給出兩種方法————形式分數求解(如果實在不懂,可從數學選修4-6,37頁自行學習)

1.乘式求解

我們換種形式,然后分子、分母同乘以與m互素的正整數n后,在分別對分子、分母%m,使用等式右邊變成整數,便得到方程唯一的解。(當然,我們要的解范圍要在0到m之間)

 是不是沒聽懂??我來給你舉個例子:7x≡8(%10)   求解x

變換形式得到x≡8/7≡8*3  /  7*3≡ 24%10/21%10 ≡4/1≡4(mod10)

其中,那個3就是“與m互素的正整數”,這可以是任何數,但是我要滿足原分母(7)乘上這個數之后能模 m(就是10)之后余1(余1的目的是最后可以得到整數),所以其實核心就是經過多次變換,把分母變成1,求得解。

 2.加式求解

我們依舊把他換成的形式,在分子上加上m的倍數,使新分子和分母有公約數,再約去它。最終得到的就是解。核心其實也就是讓b一直加m,一直加到能讓分子能整除分母即可;

 

3.擴展歐幾里得算法(在后面我會講到)

 

那我總結一下吧(其實是賀的老師的PPT)

1. 一般的線性同余方程為ax≡b(%m),其中a≠0,b,m均為已知數,x為未知數

2.這類方程解法:先將原方程化為ax+my=b的不定方程,根據b能否整除gcd(a,m)判斷方程是否有解,然后再用剛才說的那三種方法求解

3.若”d=(a,m) | b” ,b不能被d整除,則方程ax≡b(%m)無解, 否則在%m的完全剩余系{0,1,2....m-1}中,恰有d個解,第一個解為:

x0=x' * (b/d) %m,其余d-1個解可以通過對%n加上(m/d)的倍數得到,即xi=(x0+i*(m/d))%m, (1≤i≤d-1).(拓歐幾里得)

 

代碼部分:

解ax≡b(modm)方程

 要求:輸入三個非零整數a,b,m空格間隔。(a,b,m整型范圍內),輸出x的同余解,如果無解輸出“no answer!”

 

這是解法一(擴展歐幾里得)

#include<iostream>
using namespace std;
int a,b,m;
int ex_gcd(int a,int b,int &x,int &y)
{
    if(b==0) 
    {
        x=1,y=0;return a;
    }
    int x1,y1;
    int d=ex_gcd(b,a%b,x1,y1);
    x=y1;
    y=x1-a/b*y1;
    return d;
}
void mod_f(int a,int b,int m)
{
    int d,x,y,e,i;
    d=ex_gcd(a,m,x,y);
    if(b%d!=0)
    {
        printf("no answer!");
    }
    else
    {
        e=(x*(b/d)+m)%m;
        for(i=0;i<d;i++)
        printf("%d ",(e+i*(m/d))%m);
    }
}
int main()
{
    cin>>a>>b>>m;
    mod_f(a,b,m);
    return 0;
}

關於擴展歐幾里得算法我求了求旁邊的大佬幫我講了一遍,我好像是懂了吧,就是這個意思:
首先還要再提一下關於歐幾里得算法和裴蜀算法哈哈

1.歐幾里得算法就是輾轉相除法,即gcd(a,b)=gcd(b,a%b)

2.裴蜀算法:

a,b是整數,如果c=gcd(a,b),那么對於任意整數x,y,a*x+b*y是c的倍數。

今天我們運用的是當gcd(a,b)|c時,x,y的不定方程a*x+b*y=c(a,b,c均為整數)有整數解無數個

下面給出證明(我分為gcd(a,b)|c和不滿足gcd(a,b)|c)

設r=gcd(a,b)

那么我們可以表示一下a=nr,b=mr,c=qr

y=(c-a*x)/b=(qr-nr*x)/mr=(q-n*x)/m

我們不難看出:若gcd(a,b)|c的話,q就是整數。 因為y=(q-n*x)/m,所以若y是整數,總有x是整數滿足這個式子(即有x使得y為整數),所以有無數組解。

 然而,如果c不能整除gcd(a,b),也就是q為小數,我們還是看y=(q-n*x)/m這個式子,(其中q是小數,m、n是整數),如果y是整數,那么由於m是整數,可以推出q-n*x一定為整數,又由於q是小數、n是整數,可以推出x一定為小數。  依照此方法,我們也可以順利地推出若x是整數,y一定不是整數,即x,y一定不能同時取整。

 

ok,那么我們可以進入正題了,下面是正規題解(前兩步是復制粘貼的是旁邊大佬的,yyds)

首先第一步,是根據貝祖定理判斷有無整數解(gcd(a,b)|c則有整數解)。那么c=n*gcd(a,b),則設x=n*q,y=n*p。所以a*q+b*p=gcd(a,b)。

接着是第二步,是運用歐幾里得算法得到a*q+b*p=gcd(a,b)=gcd(b,a%b)=b*q`+(a-a/b*b)*p`=a*p`+b*(q`-a/b*p`)。

現在我們前后比對一下,a*q+b*p=a*p`+b*(q`-a/b*p`),可以看出,q對應的就是p’,而p對應的是q`-a/b*p`

(下面這句也是復制的大佬的)從而推出q,p的一組整數解,*n可得x,y的一組整數解,最終整數解有(x-k(b/gcd(a,b)),y-k(a/gcd(a,b)),因為k有無數個,所以整數解由無數個

最后一步我怎么着都看不懂了,就有問了問旁邊的大佬,他是那么說的:

首先我們這樣寫:

a(x-k(b/gcd(a,b)))+b(y+k(a/gcd(a,b)))=c;

我們化簡一下就會得到ax-abk/gcd(a,b)+by+abk/gcd(a,b)=c;

約一下就得到ax+by=c;

所以不難看出,對於任意的k(b/gcd(a,b))和k(a/gcd(a,b))(其中k是常數,可以是任何數)

對於x,每過一個a/gcd(a,b)就會產生一組新的解,對於y,每過一個b/gcd(a,b)就會一組新的解。

所以就會有x-k(b/gcd(a,b)),y-k(a/gcd(a,b)組解。因為k可以是任何數,所以有無數組解。

下面我再給你舉個例子:

 

 首先,我們可以通過gcd(a,b)=gcd(b,a%b)這個遞歸解得gcd(a,b)是多少,並要記錄每一次的a/b,然后我們再看最后兩列,我們要從下往上推,先用6/3得到2,讓x=2,y=0,這樣我們就得到了最低行的等式,即ax+by=6(即3*2+0=6);就這樣,我們再讓x等於y1,讓y等於x1-[a-b]*y1(我們把x和y定義為新的解,而x1和y1為原來的解),這樣我們又得到了第二組的等式ax+by=6 (即6*0+2*3=6)那我們就能明白他的用意了,其實每一行的a,b,x,y都能滿足那個ax+by=6的等式,一開始a是3,b是0,然后一直推推推,讓x=y1,y=x1-[a-b]*y1,得到新的等式,最后a會變成99,b會變成78,此時推過來的x和y,就是可以滿足這個等式的解

其實代碼也就是這樣體現的。

 

這是解法二 ———形式分數加法代碼

 其實思路就是我剛才講的,直接上代碼吧(還是復制PPT)

 

 

 

解法三————形式分數乘法

思路也是剛才提到的,也直接上代碼吧(復制PPT)

 

 

 

那你可能就頓悟怎么解多元一次不定方程了吧,不接受任何反駁

上例題!

輸入a,b,c,d,n 請找出一組整數解(x1,x2,x3,x4)滿足:a*x1+b*x2+c*x3+d*x4=n

思路就是這樣的: 我們先與處理掉gcd(a,b,c),然后原式就變成了 gcd(a,b,c)*y1+d*x4=n;我們運用所學知識就可以解出一組解,解出x4,d和y1;

然后列出第二組方程,a*x1+b*x2+c*x3=gcd(a,b,c)*y1  由於我們能求出gcd(a,b,c)而且已經求出了y1,我們就可以得到新的一組方程,然后一直重復以上操作,就可以得出一組解集

代碼如下

 

 

 

 

 

 好了,終於講完了!!

太傷元氣了,我要去開擺了,再見!!

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM