码迷,mamicode.com
首页 > 其他好文 > 详细

解线性同余方程组

时间:2018-02-02 11:32:14      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:问题   clu   ==   同余   答案   include   存在   for   pre   

想必学完exgcd的各位dalao们都已经明白如何求解同余方程了

今天本蒟蒻只是想讲讲线性同余方程组的解法供各位大佬批评指错

我们现在有一些线性同余方程

X=b1 (mod a1)

X=b2 (mod a2)

...

X=bn (mod an)

对于前面第一个方程,我们可以用exgcd求出一个X满足一式

不妨设X=a1*y1+b1

若存在X满足二式,则a1*y1+b1=b2 (mod a2)

所以y1=(b2-b1)/a1 (mod a2)

该式有解当且仅当(b2-b1)|gcd(a1,a2)

所以a1y1+a2y2=b2-b1

那么我们就可以用exgcd求出y1的解,进而求出X

那么问题来了,一式二式合并后是什么呢?

我们可以证明在lcm(a1,a2)中有且仅有一个X满足条件,利用一些初中同余知识就可以,在这里就不详细证明了

由此我们得到一个新方程X=X(mod lcm(a1,a2))

用这个方程再和后面的方程合并,for example,anslcm(a1,a2)+a3y3=b3-X

这样一个一个往下求便可以求出答案

下面是一个裸的模板

#include<cstdio>    
#define ll long long            
ll x,m,M,r,y,z;
ll gcd(ll a,ll b) {return a%b==0 ? b:gcd(b,a%b);} 
void inv(ll a,ll b) {
    if (a%b==0) 
    {z=0; y=1; return;}
    inv(b,a%b);
    ll r=z;
    z=y,y=r-a/b*y;
}
int main()
{
    int n;
    scanf("%d",&n);
    x=0; m=1;
    for (int i=1;i<=n;i++){
        scanf("%lld%lld",&M,&r);
        ll b=r-x,d=gcd(m,M);
        if (b%d!=0) {
            printf("-1");
            return 0;
        }
        inv(m/d,M/d);
        ll t=b/d*z%(M/d);
        x=x+m*t;
        m*=M/d;
    }
    printf("%lld\n\n",x>0 ? x:x+m);
    return 0;
}

解线性同余方程组

标签:问题   clu   ==   同余   答案   include   存在   for   pre   

原文地址:https://www.cnblogs.com/Cool-Angel/p/8403536.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!