单变元模线性方程算法及证明

题目

已知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;

}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值