数论 —— 线性同余方程组与中国剩余定理

【线性同余方程组】

由若干个线性同余方程构成的线性方程组。

例如:

\left\{\begin{matrix}x\equiv b_1(mod\:m_1) \\ x\equiv b_2(mod\:m_2) \\ ... \\x\equiv b_n(mod\:m_n) \end{matrix}\right.

其解法最早由我国《孙子算经》给出,因此解法称为“孙子定理”,又叫“中国剩余定理”,实质即为求多个数的最小公倍数。

【中国剩余定理】

1.内容

设自然数 m_1,m_2,...,m_n 两两互质,并记 N=m_1*m_2*...*m_n,则同余方程组:\left\{\begin{matrix}x\equiv b_1(mod\:m_1) \\ x\equiv b_2(mod\:m_2) \\ ... \\x\equiv b_n(mod\:m_n) \end{matrix}\right. 在模 N 同余的意义下,有唯一解:x=(b_1x_1+b_2x_2+...+b_nx_n)mod\:N

2.证明

考虑方程组:\left\{\begin{matrix}x\equiv 0(mod\,\:m_1) \\ ... \\x\equiv 0(mod\,\:m_{i-1}) \\x\equiv 1(mod\,\:m_{i}) \\x\equiv 0(mod\,\:m_{i+1}) \\... \\x\equiv 0(mod\,\:m_{r}) \end{matrix}\right.,1\leqslant i\leqslant r

由于 m_i 两两互质,对方程组作变量替换,即令 x=(N/m_i)*y

故方程组等价于解同余方程:(N/m_i)y\equiv 1(mod \:m_i)

若想得到特解 y_i

只要令 x_i=(N/m_i)*y_i 即可

故方程组的解为:x=b_1x_1+b_2x_2+...+b_rx_r(mod\:N),在模 N 下值唯一。

3.应用

中国剩余定理就是用来求线性同余方程组的,即对方程组:\left\{\begin{matrix}a\equiv B[1](mod\:W[1]) \\ a\equiv B[2](mod\:W[2]) \\ ... \\a\equiv B[n](mod\:W[n]) \end{matrix}\right.,在 W、B 的值已知,且 W[i]>0,W[i] 与 W[j] 互质,求 a 的值。

4.实现

#include<iostream>
using namespace std;
int Extended_GCD(int a,int b,int &x,int &y){
    if(b==0){
        x=1;
        y=0;
        return a;
    }
 
    int gcd=Extended_GCD(b,a%b,y,x);
    y=y-a/b*x;
    return gcd;
}
int China(int W[],int B[],int k){//W除数,B余数
    int mod=1;
    for(int i=0;i<k;i++)//计算mod的大小
        mod*=W[i];

    int res=0;
    int x,y,m;
    for(int i=0;i<k;i++){
        m=mod/W[i];
        Extended_GCD(W[i],m,x,y);//求出每一组W[i]与m的解
        res=(res+y*B[i]*mod/W[i]+mod)%mod;//累加所有解
    }
    return (res+mod)%mod;
}

【不互素的中国剩余定理】

对于不互素的中国剩余定理, 即:a[1],a[2],.....,a[n],不互素的情况,只能每两个一组的求解,有:

\begin{matrix}x\:mod\:a1= r1 \\ x\:mod\:a2 = r2 \end{matrix}

设:k1、k2 ,易得:\begin{matrix}x = a1*k1 + r1 \\ x = a2*k2+r2 \end{matrix}

即:a1*k1 = (r2-r1) + a2*k2

对整个式子进行 a2 取余,得:(a1*k1)\:mod\:a2 = (r2-r1)\:mod\:a2

此时式子只有一个未知量 k1,使用扩展欧几里得定理可求出 k1,从而计算出:x = a1*k1+r1

这个 x 仅是满足 \begin{matrix}x\:mod\:a1= r1 \\ x\:mod\:a2 = r2 \end{matrix} 的一个特解,不一定是 x\:mod\:a3 = r3 的解,因此要想求出式子真正的解,需要取 x 对 a1、a2 最小公倍数的模

即:ans \equiv x\:mod\:LCA(a1,a2)

由于只有 ans 是未知数,因此就将两个式子转换为一个式子,通过这样不断的合并,可以求出最终的结果。

判断是否有解,在扩展欧几里得中求 k1 时判断即可。

int Extended_GCD(int a,int b,int &x,int &y){
    if(b==0){
        x=1;
        y=0;
        return a;
    }

    LL gcd=Extended_GCD(b,a%b,y,x);
    y=y-a/b*x;
    return gcd;
}
int GCD(int a,int b){
    return b==0?a:GCD(b,a%b);
}
int CRT(int W[],int B[],int n)//w为除数,b为余数,n为有多少式子
{
    int res=B[0],Wi=W[0];
    for(int i=1;i<n;i++)
    {
        int bi=B[i],wi=W[i];
        int x,y;
        int gcd=Extended_GCD(Wi,wi,x,y);
        int c=bi-res;

        if(c%gcd!=0)//表示没有结果
            return -1;

        int M=wi/gcd;
        res+=Wi*( ((c/gcd*x)%M+M) % M);
        Wi*=M;
    }
    if(res==0)//除数全为0
    {
        res=1;
        for(int i=0;i<n;i++)
            res=res*W[i]/GCD(res,(LL)W[i]);
    }
    return res;
}
int a[N],b[N];
int main(){
    int k;
    while(scanf("%d",&k)!=EOF&&k){
        for(LL i=0;i<k;i++)
            scanf("%d%d",&a[i],&b[i]);//先除数后余数
        printf("%d\n",CRT(a,b,k));
    }
    return 0;
}

【例题】

  • Biorhythms(POJ-1006)(中国剩余定理)点击这里
  • Monkey Tradition(LightOJ-1319)(中国剩余定理)点击这里
  • Strange Way to Express Integers(POJ-2891)(不互素的中国剩余定理)点击这里
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值