中国剩余定理(又称孙子定理)

中国剩余定理,又名孙子定理

1、

首先:

能求解什么问题呢?

问题:

一堆物品

3个3个分剩2个

5个5个分剩3个

7个7个分剩2个

问这个物品有多少个

 

解这题,我们需要构造一个答案

我们需要构造这个答案

5*7*inv(5*7,  3) % 3  =  1

3*7*inv(3*7,  5) % 5  =  1

3*5*inv(3*5,  7) % 7  =  1

这是逆元

 

然后两边同乘你需要的数

2 * 5*7*inv(5*7,  3) % 3  =  2

3 * 3*7*inv(3*7,  5) % 5  =  3

2 * 3*5*inv(3*5,  7) % 7  =  2

 

a = 2 * 5*7*inv(5*7,  3) 

b = 3 * 3*7*inv(3*7,  5) 

c = 2 * 3*5*inv(3*5,  7) 

那么

a % 3 = 2

b % 5 = 3

c % 7 = 2

其实答案就是a+b+c

因为

a%5 = a%7 = 0 因为a是5的倍数,也是7的倍数

b%3 = b%7 = 0 因为b是3的倍数,也是7的倍数

c%3 = c%5 = 0 因为c是3的倍数,也是5的倍数

所以

(a + b + c) % 3 = (a % 3) + (b % 3) + (c % 3) = 2 + 0 + 0 = 2

(a + b + c) % 5 = (a % 5) + (b % 5) + (c % 5) = 0 + 3 + 0 = 3

(a + b + c) % 7 = (a % 7) + (b % 7) + (c % 7) = 0 + 0 + 2 = 2

你看你看,答案是不是a+b+c(。・ω・)ノ゙,完全满足题意

但是答案,不只一个,有无穷个,每105个就是一个答案(105 = 3 * 5 * 7)

 

根据计算,答案等于233,233%105 = 23

如果题目问你最小的那个答案,那就是23了


另外一种解释:

一堆物品

3个3个分剩2个

5个5个分剩3个

7个7个分剩2个

问这个物品有多少个?

首先假如我们求出这样三个数k1,k2,k3,满足 k1与3互质且是5和7的倍数,k2与5互质且是3,7的倍数,k3与7互质且是3和5的倍数

那么容易意会得到,k1∗2+k2∗3+k3∗2   一定会是一个满足题目条件的数。
而题目的通解可表示为这个数每次都加上3,5,7的最小公倍数


辣么如何求出k1,k2,k3呢?

首先我们求出3,5,7的lcm=105
然后我们令:
x1=105/3=35
x2=105/5=21
x3=105/7=15
然后我们求解以下方程:
a∗x1%3=1         //   a×x1是k1,a×x1%3=1,那么2×a×x1%3=2与题意相符
b∗x2%5=1
c∗x3%7=1
啊呀这个格式的式子好眼熟。。。那么就愉快地用扩展欧几里德求出来吧!
a=2,b=1,c=1  (用扩展欧几里德求出的)
答案就是:
ans=(a∗x1∗2+b∗x2∗3+c∗x3∗2)%lcm=23
其中

k1=a*x1=2*35=70 

k2=b*x2=1*21=21

k3=c*x3=15*1=15;

所以满足条件的是   ( 70×2+21×3+15×2 ) %105 =23

结果是  23


2、

以下抄自百度百科

中国剩余定理给出了以下的一元线性同余方程组:

中国剩余定理1

 

中国剩余定理说明:假设整数m1,m2, ... ,mn两两互质,则对任意的整数:a1,a2, ... ,an,

 方程组(S)

有解,并且通解可以用如下方式构造得到:设

 中国剩余定理2

是整数m1,m2, ... ,mn的乘积,并设

 中国剩余定理3

是除了mi以外的n- 1个整数的乘积。设

 中国剩余定理4

这个就是逆元了

 中国剩余定理5 

通解形式为

 中国剩余定理6 

在模M的意义下,方程组(S)只有一个解:

 中国剩余定理7


Code:

#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
LL a[101];
LL b[101];
LL ex_gcd(LL a,LL b,LL &x,LL &y,LL &d) // 求逆元
{
    if(a==0&&b==0)
        d=-1;
    if(b==0)
    {
        x=1;
        y=0;
        d=a;
    }
    else{
        ex_gcd(b,a%b,y,x,d);
        y-=(a/b)*x;
    }
}
LL CRT(LL n)  // 中国剩余定理( CRT )
{
    LL sum=1;
    for(LL i=0;i<n;i++)
        sum*=a[i]; // 最小公倍数
    LL ans=0;
    for(LL i=0;i<n;i++){
        LL x,y,d;
        LL t=sum/a[i]; 
        ex_gcd(t,a[i],x,y,d); // 用扩展欧几里德 求 “系数”——  1
        ans=(ans+t*x*b[i])%sum; // 最后结果 ———————— 2
    }
    return (ans+sum)%sum;
}
int main()
{
    LL k,n;
    cin>>n;
    for(LL i=0;i<n;i++)
        scanf("%lld %lld",&a[i],&b[i]); 
    cout<<CRT(n)<<endl;
}

解释一下

1——: 求出来的是系数,类似于上边 1 中讲的 a、b、c

2——: 求的是最后的结果,直接套 这个式子  ans=(a∗x1∗2+b∗x2∗3+c∗x3∗2) // x1 是 t=sum / a[ i ]

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值