中国剩余定理

前置知识:

  逆元定义:满足ax≡1(mod m)的整数x为a对模m的数论倒数或逆元,记为a-1(mod m)或a-1(百度搜索数论倒数)

  还有取模意义下的各种运算(其实跟不取模的也没有太大差异,但是小部分还是有差异的,例如除法,这个还是自己百度吧,这里不赘述了)

行,那我们来正式开始中国剩余定理

它讲了这么一个事:求最小的数使它除以3余2,除以5余1,除以7余2

根据已知条件,我们可以得到如下结论

  x%3=2

  x%5=1

  x%7=2

抽象成为:

  x%m1=a1

  x%m2=a2

  x%m3=a3

  ......

 

于是有如下思路:找1个模m1等于a1,模m2等于a2....的数不容易,那我们就先找模m1余a1,模其它数余0的数,最后再调整到满足所有条件的

但其实这样的也不好找,那就简化成模m1余1(这不就是逆元嘛),模其它数余0的数,最后再调整到余a1

 

实际操作如下:

先找模m1余1,模其它数余0的数

记M=m1*m2*m3*...mn;

则m2*m3*...mn=M/m1,记为M1;//为了使M1(最终结果的一部分)模m2,m3...mn等于0

记t1为M1在模m1意义下的逆元//这样就使M1*t1模m1等于1,继承上面,模m2,m3...mn等于0

那么我们就完成了第一步

接下来给t1*M1乘上a1我们就可以得到模m1余a1的数了(M1*t1%m1=1-->M1*t1*a1%m1=a1)

记M1*t1*a1=x1

第二步就完成了

接下来对每一对ai,mi都进行如上操作,得到x1,x2,x3...xn;

将x1,x2,x3..xn相加得到最终结果x0

最后的最后需要将x0 mod M才能得到x,为了把x0调整为最小的数(这里还可以证明:在1-M的范围内,有且仅有一个x满足上述条件,证明可用反证法,假设有2个,最后相减等于0,证明2解相等,即为1解)

接下来是模板

//a[i]一定要互质才行!!!! 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define int long long
using namespace std;
int a[15],b[15],n,ls,y,x,mod;
int exgcd(int a,int b,int &x,int &y)//扩欧求逆元
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    int r=exgcd(b,a%b,x,y);
    int t=x;
    x=y;
    y=t-a/b*y;
    return r;
}
signed main()//因为上面#define int long long了 
{
    scanf("%lld",&n);
    for(int i=1;i<=n;i++) scanf("%lld%lld",&a[i],&b[i]);//模a[i]余b[i]
    mod=1;   
    for(int i=1;i<=n;i++) mod*=a[i];
    for(int i=1;i<=n;i++)
    {
        int kkk=mod/a[i];
        exgcd(a[i],kkk,ls,y);
        x=(x+y*kkk*b[i])%mod;
    }
    int ans=(x+mod)%mod;
    printf("%lld",ans);
} 

行了,我的坑填完了

液!( •̀ ω •́ )y

posted @ 2018-10-29 22:00  小橘A  阅读(228)  评论(0编辑  收藏  举报