版权声明:侵删,转载请附带链接或评论 https://blog.csdn.net/corsica6/article/details/82177534
传送门:洛谷:p4777
中国剩余定理(CRT)
给定 ( 分别为互不相同的素数),求解满足上式的最小非负整数解 。
设 , ,
显然,
扩展中国剩余定理(EXCRT)
要求同上,唯一不同的是 为任意正整数,不要求为素数,也不要求互质。
采用增量法:
设当前已求出满足前 项的答案 , 。
必然存在整数 ,使得:
也即:
故:
变成了扩展欧几里得的形式。
先求出
则 (若 不能被 整除,则无解)
不断增量即可。
代码
这里的 的定义可以参考洛谷题面。
#include<bits/stdc++.h>
#define RI register
#define gc getchar
using namespace std;
typedef long long ll;
const int N=1e5+10;
int n;
ll a,b,ans,mod,Mod,res,tp,x,y,k;
char c;
template<class T>
inline void rd(T &x)
{
c=gc();x=0;
for(;!isdigit(c);c=gc());
for(;isdigit(c);c=gc()) x=x*10+(c^48);
}
inline ll gcd(ll A,ll B){return (!B)?A:gcd(B,A%B);}
inline void exgcd(ll A,ll B)
{
if(!B){x=1;y=0;return;}
exgcd(B,A%B);
k=x;x=y;y=k-y*(A/B);
}
inline ll mul(ll x,ll y,ll md)//O(1)快速乘
{ll d=floor(1.0*x/md*y+1e-8);ll re=x*y-d*md;return re<0?re+md:re;}
int main(){
rd(n);
rd(mod);rd(ans);
for(RI int i=2;i<=n;++i){
rd(a);rd(b);tp=gcd(mod,a);//先求出gcd会快一些
if(ans%a==b){mod=mod/tp*a;continue;}
res=((b-ans)%a+a)%a;res/=tp;Mod=a/tp;
exgcd(Mod,mod/tp);
y=(mul(y,res,Mod)+Mod)%Mod;
Mod*=mod;ans=(ans+mul(y,mod,Mod))%Mod;
mod=Mod;
}
printf("%lld\n",ans);
}