中国剩余定理
前置知识:
逆元定义:满足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