擴展歐幾里德算法——求最小整數解


這是一個數學推導!!!

 

首先我們已經知道了,如何通過擴展歐幾里德算法,求出方程的其中一組解了

那么就可以繼續往下看

  

  給出兩個方程

    ax1+by1=gcd(a,b)

    ax2+by2=gcd(a,b)

  所以可以推出

    ax1+by1=ax2+by2

    a(x1-x2)=b(y2-y1)

  然后我們知道gcd(a,b)為a,b的最大公因數,所以我們將 A=a/gcd(a,b),B=b/gcd(a,b),接着往下推出

    A(x1-x2)=B(y2-y1)

  現在A和B兩個已經是互素了,所以又可以接着推出

    (這個地方要好好理解,重點!)

    A*(n*B)=B*(m*A)

    (x1-x2)=n*B

    (y2-y1)=m*A

  這里我們從x入手

    (x1-x2)=n*B

    x1=x2+n*B

  由此,我們推出了x解的通解公式    x=x0+n*B

  同理,我們推出了y解的通解公式 y=y0-m*A

 

  那么我們如果要求 x 的最小整數解,也就是 x0, 就是 x0=x%B

  如果我們要求的是  ax+by=c,還得先轉化  x=x*c/gcd(a,b).

  然后套入我們的公式

  B=b/gcd(a,b)

  x0=x%(b/gcd(a,b))

  嗯,到此結束,下面給下實現代碼

 

#include <bits/stdc++.h>
#include<unordered_set>
//freopen("in.txt", "r", stdin);

using namespace std;
typedef double dou;
typedef long long ll;
typedef pair<ll, ll> pii;

#define M 1050
#define inf 0x3f3f3f3f
#define mod 1000000007
#define W(a) while(a)
#define lowbit(a) a&(-a)
#define left k<<1
#define right k<<1|1
#define ms(a,b) memset(a,b,sizeof(a))
#define debug(a) cout<<#a<<" == "<<a<<endl
#define false_stdio ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)

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

ll solve(ll a, ll b, ll c) {
    ll x, y, z;
    z = exgcd(a, b, x, y);
    if (c%z)return -1;//不成立
    //return x; //不需要最小正整數的話直接返回x
    x *= c / z;
    b = abs(b / z);
    return (x%b + b) % b;
}

int main() {
    false_stdio;
    ll a, b, c;
    cin >> a >> b >> c;
    
    ll x = solve(a, b, c);
    ll y = (c - x * a) / b;
    
    if(x>=0)//看x大小要求而定
        cout << x << ' ' << y << endl;
        
    

    return 0;
}

 


免責聲明!

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



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