中国剩余定理

中国剩余定理:
中国剩余定理(孙子定理)是用于解决一次同余方程组的一种方法。
定理的思路是将两个同余方程合为一个再下一个方程合并,最后得到答案。

那么先来看看对于两个方程的合并:

x = a1(mod n1)
x = a2(mod n2)

将方程都转换为乘积与和的形式:

x = n1 * T1+a1
x = n2 * T2+a2

将上述两式合并整理得:

n1T1=(a2-a1)+n2T2

设gcd(n1,n2) = d,c = a2 - a1,则合并的同余方程可变形为

(n1/d)*T1 = (c/d)(mod n2/d)

T1 =(c/d)*(n1/d)^-1(mod n2/d)

不妨设S = (c/d)(n1/d)^-1,则T1=t(n2/d) + S,那么

x = n1[t*(n2/d)+S]+a1 = (n1n2/d) t + n1S+a1,即x = n1S+a1(mod n1*n2/d)

那么在带入求解时新的a3 = n1S + a1,n3 = n1n2/d,最终,其中最小的x就是最后剩余的方程的a(mod n)

#include"iostream"
using namespace std;
typedef long long LL;
LL r[1001],m[1001],N; 
LL gcd(LL a,LL b){
    return b?gcd(b,a%b):a;
}
LL ex_gcd(LL a,LL b,LL &x,LL &y){
    if(b == 0){
        x = 1;
        y = 0;
        return a;
    }
    LL d = ex_gcd(b,a%b,x,y);
    LL t = x;
    x = y;
    y = t -(a/b)*y;
    return d;
    
}
LL Inv(LL a,LL b){
    LL d = gcd(a,b);
    if(d!=1)return -1;
    LL x,y;
    ex_gcd(a,b,x,y);
    return (x%b+b)%b;
}
bool megre(LL r1,LL m1,LL r2,LL m2,LL &r3,LL &m3){
    LL d = gcd(m1,m2);
    LL r = r2-r1;
    if(r%d)return 0;
    r = (r%m2+m2)%m2;
    m1/=d;m2/=d;r/=d;
    r*=Inv(m1,m2);
    
    r%=m2;r*=m1*d;r+=r1;
    
    m3 = m1*m2*d;
    
    r3 = (r%m3+m3)%m3;
    return 1;
    
}
LL CRT(){
    LL A1 = r[1],B1 = m[1];
    for(int i = 2;i <= N;i++){
     LL A2 = r[i],B2 = m[i];
     LL A3,B3;
     if(!megre(A1,B1,A2,B2,A3,B3))return -1;
     A1 = A3;
     B1 = B3;   
    }
    return (A1%B1+B1)%B1;
}
int main(){
     cin >> N;
     for(int i = 1;i <= N;i++)
     cin >> m[i];
     for(int i = 1;i<= N;i++)
     cin >> r[i]; 
     cout <<CRT();
    return 0;
}

转载于:https://www.cnblogs.com/PHKCOOL/p/10946602.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值