1. 程式人生 > >單變元模線性方程演算法及證明

單變元模線性方程演算法及證明

題目

已知a,b,n,求x,使得ax=b(mod n).

演算法說明

令d=gcd(a,n),如果d|b,則存在d個解。否則無解。
用擴充套件歐幾里得演算法求出 ax+ny=d 的一組解(x0,y0).x0即為ax=b(mod n)的一個解。d個解滿足x=x0+i*n/d,i取值範圍是[0,d-1].

推導過程

由同餘方程的定義,可知ax-ny=b.
將b拆分為gcd(a,n)*t.
若gcd(a,n)不能整除b,因為ax0+ny0=gcd(a,n).等式左邊有因子gcd(a,n),而等式右邊沒有,所以此時是無解的。
設x0,y0滿足ax0+ny0=gcd(a,n).
等式兩邊同乘以t,得
a(x0*t)-n(-y0*t)=gcd(a,n)*t.
即x0*t為ax=b(mod n)的一個解。

通解證明:
設(x1,y1)和(x2,y2)是ax-ny=b的解。
ax1 - ny1 = b; …(1)
ax2 - ny2 = b; …(2)
(2) - (1),得:
a(x2 - x1) = n(y2 - y1)
等式兩邊同時除以d,d=gcd(a,n).得:
a/d * (x2 - x1) = n/d * (y2 - y1).
因為 a/d 和 n/d互質了,所以(x2 - x1)一定是 n/d 的倍數,即
x2 - x1 = n/d * i.

i的最大取值為d - 1.因為如果 i = d 的話,x2 - x1 = n.
ax2 = b(mod n).即
a(x1 + n) = b(mod n),
ax1 + a*n = b(mod n).
x2和x1是模n下的同一個解。所以i的取值範圍是[0,d-1].

程式碼

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

ll ex_gcd(ll a,ll b,ll &x,ll &y)
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    else
    {
        ll r=ex_gcd(b,a%b,x,y);
        ll t=x;
        x=y;
        y=t-y*a/b;
        return
r; } } vector<ll> cm(ll a,ll b,ll n) { ll x,y; vector<ll> ans; ans.clear(); ll d=ex_gcd(a,n,x,y); if(b%d==0) { ans.push_back(x*(b/d)%n); for(ll i=1; i<d; i++) ans.push_back((ans[0]+i*n/d)%n); return ans; } } int main() { ll a,b,n; while(cin>>a>>b>>n) { vector<ll> ans=cm(a,b,n); for(ll i=0;i<ans.size();i++) cout<<ans[i]<<endl; } return 0; }