线性同余方程的解法笔记

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;

int gcd(int a,int b){
    return (b==0? a:gcd(b,a%b));
}

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

int mod_inverse(int a,int m)
{
    int x,y;
    exgcd(a,m,x,y);
    return (m+x%m)%m;
}

pair<int,int> linear_congruence(const vector<int>&A,const vector<int>&B,const vector<int>&M)
{
    int x=0,m=1;
    for(int i=0;i<A.size();i++){
        int a=A[i]*m,b=B[i]-A[i]*x,d=gcd(M[i],a);
        if(b%d!=0) return make_pair(0,-1);
        int t=b/d*mod_inverse(a/d,M[i]/d)%(M[i]/d);
        x=x+m*t;
        m*=M[i]/d;
    }
    return make_pair(x%m,m);
}


做下小笔记,上面的代码都是copy<<挑战程序设计竞赛>>这本书的,下面主要是对求线性同余方程组的解的一些笔记.

求解线性同余方程组的思想就是利用x=b1(mod m1) (I) 和 ax=b2(mod m2) (II)解出一组新的x'=b'(mod m')然后里用新的这组继续去解 ax=b3(mod m3)

解的过程 首先利用 x=b1(mod m1)可以写成 x=b1+m1*t代入(II)整理得到:

am1*t=b2-a*b1(mod m2),利用扩展欧几里德可以知道,该方程有解当且仅当d=gcd(am1,m2)|(b2-a*b1),当满足这个条件时原方程等价于

(am1/d)*t=((b2-a*b1)/d)mod(m2/d)  利用逆元的求法(实质是扩展欧几里德)可以解出来

t=((b2-a*b1)/d)*mod_inverse(am1/d,m2/d) (mod m2/d)

即解出k值使得t=k(mod m2/d),即 t=k+(m2/d)*c(c为整数)

回代到x=b1+m1*t里有 x=b1+m1(k+(m2/d)*c);

x=b1+m1*k+m1*(m2/d)*c

所以新的一组解是 x=b1+m1*k(mod m1*(m2/d))

利用这个方法迭代下去就可以解粗来了~

貌似当要解的方程是这样的时候  x=bi(mod ai) i=0,1,2,3...且ai,aj两两互质时可以用中国剩余定理做,不过不太懂.- -0

笔记结束.

 

 

转载于:https://www.cnblogs.com/chanme/p/3207412.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值