码迷,mamicode.com
首页 > 其他好文 > 详细

中国剩余定理

时间:2019-01-09 20:31:08      阅读:243      评论:0      收藏:0      [点我收藏+]

标签:百度百科   bre   long   形式   matrix   display   信息   occurs   www.   

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

三人同行七十稀,五树梅花廿一支,七子团圆正半月,除百零五使得知

——《孙子算经》


它可以做什么?

中国剩余定理可以用于解决形如以下形式的线性同余方程组

\[(X)\left\{\begin{matrix}x_1\equiv b_1\pmod{m_1}\\x_2\equiv b_2\pmod{m_2}\\\ldots\\x_n\equiv b_n\pmod{m_n}\end{matrix}\right.\]

其中\(m_1,m_2,m_3,\ldots,m_n\)两两互质

它是怎么做的?

中国剩余定理利用构造法给出了一组解,构造方法如下:

\(M=\prod_{i=1}^nm_i\),并设\(M_i=M/m_i\),即\(M_i=\prod_{j=1,j\neq i}^nm_j\)
\(t_i=M_i^{-1}\)\(M_i\)\(m_i\)意义下的逆元,那么同余方程组\((X)\)的通解可以表示为以下形式:

\[x=\sum_{i=1}^nb_iM_it_i+kM,M\in\mathbb{Z}\]

在模\(M\)意义下,方程组的解为:

\[x=(\sum_{i=1}^nb_iM_it_i)\pmod{M}\]

为什么是正确的?

证明如下:

由于\(m_1,m_2,m_3,\ldots,m_n\)两两互质,因此有\(\gcd(M_i,m_i)=1\),所以存在\(t_i\)满足\(M_it_i=1\pmod{m_i}\)

于是有:\(b_iM_it_i\equiv b_i*1\equiv b_i\pmod {m_i}\)

且对于\(\forall j\in\{1,2,3,\ldots,n\},j\neq i\),有\(b_iM_it_i\equiv0\pmod{m_j}\)

那么对于\(\forall i\in\{1,2,3,\ldots,n\}\)\(x=\sum_{i=1}^nb_iM_it_i\)满足:

\[x\equiv b_iM_it_i+\sum_{j=1,j\neq i}^nb_jM_jt_j\pmod{m_i}\equiv b_i*1+\sum_{j=1,j\neq i}^n0\pmod{m_i}\equiv b_i\pmod{m_i}\]

由此可以证明\(x\)是同余方程组\((X)\)的一个解

另外,若\(x_1,x_2\)都是方程组\((X)\)的解,那么

对于\(\forall i\in\{1,2,3,\ldots,n\},x_1-x_2\equiv0\pmod{m_i}\)

\(m_1,m_2,m_3,\ldots,m_n\)两两互质,所以\(M|(x_1-x_2)\),这说明方程组\((X)\)的任意两个解之间相差\(kM,k\in\mathbb{Z}\)

那么方程组的所有整数解的形式即为:

\[x=\sum_{i=1}^nb_iM_it_i+kM,M\in\mathbb{Z}\]

Code

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#define maxn 105
using namespace std;

int n;
int b[maxn],m[maxn],lcm=1,M[maxn],t[maxn];

int exgcd(int a,int p,int &x,int &y)
{
    if(!p)
    {
        x=1;
        y=0;
        return a;
    }
    int xx,yy,k;
    k=exgcd(p,a%p,xx,yy);
    x=yy;
    y=xx-a/p*yy;
    return k;
}

int main()
{
    int ans=0;
    scanf("%d",&n);
    register int i;
    for(i=1;i<=n;++i)
    {
        scanf("%d%d",&b[i],&m[i]);
        lcm*=m[i];
    }
    for(i=1;i<=n;++i)
    {
        int x,y;
        M[i]=lcm/m[i];
        exgcd(M[i],m[i],x,y);
        ans=(ans+b[i]*M[i]*x)%lcm;
    }
    printf("%d",ans);
    return 0;
}

例题

UVA756 Biorhythms

Description

输入包含若干个测试点,以四个 \(-1\) 结束。

每一个测试点输入四个整数 \(p\), \(e\), \(i\)\(d\)。求最小的 \(x\),使得 \(x>d\) 并且

\[\left\{\begin{matrix}x\equiv p\pmod{23}\\x\equiv e\pmod{28}\\x\equiv i\pmod{33}\end{matrix}\right.\]

输出\(x-d\)的值

输出请按照如下格式:

Case 1: the next triple peak occurs in 1234 days.

Solution

中国剩余定理裸题,直接套用即可

Code

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdlib>
using namespace std;
typedef long long ll;

int b[4],m[4]={0,23,28,33},M[4]={0,924,759,644},t[4];
int lcm=21252;//23*28*33

void exgcd(int a,int b,int &x,int &y)
{
    if(!b)
    {
        x=1,y=0;
        return;
    }
    exgcd(b,a%b,y,x);
    y-=a/b*x;
}

void Pre()
{
    int y;
    for(int i=1;i<=3;++i)
    {
        exgcd(M[i],m[i],t[i],y);
        t[i]=(t[i]+m[i])%m[i];
    }
}

int main()
{
    Pre();
    int cas=0,d;
    while(1)
    {
        for(int i=1;i<=3;++i)
            scanf("%d",&b[i]);
        scanf("%d",&d);
        if(b[1]==-1)
            break;
        int ans=0;
        for(int i=1;i<=3;++i)
            ans=(ans+b[i]*M[i]*t[i]%lcm)%lcm;
        ans=(ans-d+lcm)%lcm;
        if(ans==0)
            ans=lcm;
        printf("Case %d: the next triple peak occurs in %d days.\n",++cas,ans);
    }
    return 0;
}

部分内容来源:
孙子定理_百度百科
《信息学奥赛之数学一本通》林厚从 著

中国剩余定理

标签:百度百科   bre   long   形式   matrix   display   信息   occurs   www.   

原文地址:https://www.cnblogs.com/lizbaka/p/CRT.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!