前言:

中国剩余定理又名孙子定理。因孙子二字歧义,常以段子形式广泛流传。

 

中国剩余定理并不是很好理解,我也理解了很多次。

CRT 中国剩余定理

中国剩余定理,就是一个解同余方程组的算法。

CRT&EXCRT 中国剩余定理及其扩展

求满足n个条件的最小的x。

看起来很麻烦。

先找一个特殊情况:$m_1,m_2,...m_n$两两互质。

这个时候,构造$M=m_1*m_2*...m_n$;

令$M_i=M/m_i$;

所以,构造$n$个数,其中第$i$个数是除$i$之外的其他所有数的倍数,并且第$i$个数$mod m_i =1$

即:$M_i x = 1 ( mod m_i ) $求出这样一个x,就求出了 这个数。

因为$m$之间两两互质,所以对于$n$个这样的方程,$x$本质上就是$M_i$在$m_i$意义下的乘法逆元。

(不会$exgcd$?左转:EXGCD 扩展欧几里得

因为互质,一定有解的。

用扩展欧几里得算就可以。

同理,构造$n$个数。$b_1,b_2....b_n$

其中,$b_i=M_i \times x_i$

那么,因为$b_i  = 1 (mod m_i)$,所以$ b_i * a_i = a_i (mod m_i)$

那么,原题目中的这个x就是:$x=(a_1\times b_1+a_2\times b_2+...+a_n\times b_n) $验证一下,是不是?

 

总得来说,

对于$mi$互质的情况,$x=\sum_1^n M_i\times a_i\times inv_i$

其中,$inv_i$表示,$M_i$在$mod\space m_i$意义下的逆元。

当然,为了保证$x$最小,要让$x$和$lcm$做一些处理。当然,因为互质,所以$lcm$就是$M$了

x=(x%M+M)%M

例题:poj1006 生理周期 Biorhythms

在CRT上的小小变形。注意开始计算的时间d就好了。上述最小的$x$就是$n+d$

答案$n=(a_1\times b_1+a_2\times b_2+a_3\times b_3-d)%lcm$

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
using namespace std;
int p,e,l;
int p1,e1,l1;
int tt,d;
void exgcd(int a,int b,int &x,int &y){
    if(b==0){
        x=1,y=0;return;
    }
    exgcd(b,a%b,y,x);
    y-=(a/b)*x;
}
int main(){
    exgcd(23*28,33,l1,tt);
    l1=(l1%33+33)%33;
    l1*=23*28;
    
    exgcd(28*33,23,p1,tt);
    p1=(p1%23+23)%23;
    p1*=28*33;
    
    exgcd(23*33,28,e1,tt);
    e1=(e1%28+28)%28;
    e1*=23*33;
    
    int lcm=23*28*33;
    int cnt=0;
    while(1){
        ++cnt;
        scanf("%d%d%d%d",&p,&e,&l,&d);
        if(p==-1) break;
        int op=(p1*p+e1*e+l1*l-d+lcm)%lcm;
        if(op==0) op=lcm;
        printf("Case %d: the next triple peak occurs in %d days.\n",cnt,op);
    }
    return 0;
}
poj1006

相关文章: