中国剩余定理(CRT) and 扩展中国剩余定理(EXCRT)

今有物不知其数,三三数之余二;五五数之余三;七七数之余二。问物几何?

语文水平不高,大概翻译一下:

今天Rothen钓了几个妹子,3个3个的数会余下2个,5个5个的数会余下3个,七个七个的数会剩下2个

好吧,这样好像更难理解了,懒得翻译了,反正大家都看得懂,大佬们就先做会吧,反正对于您这种神犇那肯定是秒切啊!。

 

中国剩余定理???好高级的东西啊,吓得我赶紧来个BFS( Baidu First Search)

发现中国剩余定理又叫孙子定理,原因是孙子发明的(这名字绝了)

然后对于上面的题目的解法为:

(注意,中国剩余定理的解法只能用于几个模数两两互质的情况)

1.首先找出5和7的 mod 3等于1的公倍数(70),然后找出3和7的mod 5 等于1的公倍数(21),还有就是3 和 5的mod 7等于1的公倍数(15)

2.答案就是上面求出来的三个数的乘积分别乘以"对应的余数" mod 所有模数的乘积 例如 (70*2+21*3+15*2)mod (7*3*5)得到23

 

纳尼!这么神奇的吗?

真的就是这么神奇哦~

本蒟蒻查阅对于这个定理的证明为:

把上面的问题转化为多个个子问题:

假设存在一个数x1 % 3 =2("%"就是取余数),那么x1就能表示为3k+2的形式(k >= 0)

假设存在一个数x2 % 5 =3("%"就是取余数),那么x1就能表示为5k+3的形式(k >= 0)

假设存在一个数x3 % 7 =2("%"就是取余数),那么x1就能表示为7k+2的形式(k >= 0)

那么考虑如果存在一个

x1 + x2 + x3使得它们满足上面的所有条件呢?

首先有个特别基础的公式:A % B = C, 那么(A + B*K) % B =C

这个应该很好理解,你可以这么想:跟上面的类似,A可以表示为 若干倍的B加上C,

而A+B*k就可以表示为:若干倍的B + C +K倍的B ,自然的对于(A+B*k)%B也是等于C了啊!

回到刚才的问题,怎么样才能使得x1+x2+x3满足条件呢?

若要使得(x1+x2+x3)%3仍然余下2,那么x2,x3就一定要是三的倍数

若要使得(x1+x2+x3)%5仍然余下3,那么x1,x3就一定要是五的倍数

若要使得(x1+x2+x3)%7仍然余下2,那么x1,x2就一定要是七的倍数

 

 所以问题就转化为了求出x1,x2,x3

哦吼,从上面我们看出了x1,x2,x3的几个性质:

1.x1是5和7的公倍数,而且x1 % 3  = 2

2.x2是3和7的公倍数,而且x2 % 5 =  3

3.x3是3和5的公倍数,而且x3 % 7 =  2

同时又引入一个数学公式:

如果a%b=c,那么(a*k)%b=(a%b+a%b+a%b+...+a%b(k个a%b)   ) mod   b=c×k mod b

然后问题就可以用开篇的方法解决了呀!而且找出来的是最小满足条件的数。

 

妙啊!

 

例题:

P1495 【模板】中国剩余定理(CRT)/曹冲养猪

 

板子,不多赘述。

 

放上我这丑的一批的代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,a[15],b[15],c[15],q=1,sum=0;
signed main(){
    cin>>n;
    for (int i = 1 ; i <= n ; i ++)
    cin>>a[i]>>b[i],q*=a[i];
    for (int i = 1 ; i <= n ; i ++){
        if(a[i] == 1)continue;
        q/=a[i];
        int j=1;
        while(q*j % a[i] != 1)j++;//找其他几个数的公倍数%a[i]等于一的数
        c[i]=q*j;
        q*=a[i];
    }
    for (int i = 1 ; i <= n ; i ++)
        sum+=c[i]*b[i],sum%=q;
    cout<<sum%q;
    return 0;
}

注意:中国剩余定理只能用于每一个a[i]都两两互质的情况,但是如果它们不是两两互质的,我们就要用   “扩展中国剩余定理

 

扩展中国剩余定理是中国剩余定理的"进阶版"

 

那么扩展中国剩余定理的使用情况是怎么样的呢?

因为上面也提到了:“注意,中国剩余定理的只能用于几个模数两两互质的情况”,所以扩展中国剩余定理就是可以适用于模数不两两互质的情况。

那这怎么搞啊?

聪明的数学家们又找到了一种办法:

将原来的余数方程列出来

假设现在我们已经求出来了前k-1个方程的解是x,现在加入了第k个方程

设前k-1个方程的模数的乘积是M,我们现在就是要求一个数字P使得

(x + P*M) % 第k个模数  = 第k个余数

这个P是可以通过扩展欧几里得算法算出来的,所以就可以很快求出P来。

 

这个问题又解决了,妙啊!

posted @ 2020-08-23 20:23  MYCui  阅读(359)  评论(12编辑  收藏  举报