【擴展歐幾里得】NOIP2012同余方程


題目描述

求關於 x 的同余方程 ax ≡ 1 (mod b)的最小正整數解。

輸入輸出格式

輸入格式:

 

輸入只有一行,包含兩個正整數 a, b,用一個空格隔開。

 

輸出格式:

 

輸出只有一行,包含一個正整數 x0,即最小正整數解。輸入數據保證一定有解。

 

輸入輸出樣例

輸入樣例#1:  復制
3 10
輸出樣例#1:  復制
7

說明

【數據范圍】

對於 40%的數據,2 ≤b≤ 1,000;

對於 60%的數據,2 ≤b≤ 50,000,000;

對於 100%的數據,2 ≤a, b≤ 2,000,000,000。

NOIP 2012 提高組 第二天 第一題

題解

順便把歐幾里得算法也寫上了

證明:

其實歐幾里得算法就是輾轉相除法。。。

擴展歐幾里得就是

對於不完全為 0 的非負整數 a,b,gcd(a,b)表示 a,b 的最大公約數,必然
 
存在整數對 x,y ,使得 gcd(a,b)=ax+by。
 
求解 x,y的方法的理解
 
設 a>b。
 
1,顯然當 b=0,gcd(a,b)=a。此時 x=1,y=0;
 
2,a>b>0 時
 
設 ax1+ by1= gcd(a,b);
 
bx2+ (a mod b)y2= gcd(b,a mod b);
 
根據朴素的歐幾里德原理有 gcd(a,b) = gcd(b,a mod b);
 
則:ax1+ by1= bx2+ (a mod b)y2;
 
即:ax1+ by1= bx2+ (a - [a / b] * b)y2=ay2+ bx2- [a / b] * by2;
 
也就是ax1+ by1 == ay2+ b(x2- [a / b] *y2);
 
根據恆等定理得:x1=y2; y1=x2- [a / b] *y2;
 
這樣我們就得到了求解 x1,y1 的方法:x1,y1 的值基於 x2,y2.
 
上面的思想是以遞歸定義的,因為 gcd 不斷的遞歸求解一定會有個時候 b=0,所以遞歸可以結束。

代碼

 

//by 減維
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<map>
#include<bitset>
#include<algorithm>
#define ll long long
#define maxn
using namespace std;

ll n,m;

ll gcd(ll x,ll y)
{
    return y?gcd(y,x%y):x;
}

ll exgcd(ll a,ll b,ll &x,ll&y)
{
    if(b==0){
        x=1,y=0;
        return a;
    }
    ll q=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return q;
}

int main()
{
    scanf("%lld%lld",&n,&m);
    ll z=gcd(n,m);
    n/=z,m/=z;
    ll x,y;
    ll asd=exgcd(n,m,x,y);
    printf("%lld",(x+m)%m);
}

 


免責聲明!

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



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