中国剩余定理及扩展模板
m互质的情况:中国剩余定理
洛谷 P3868 [TJOI2009]猜数字
数据比较卡,所以要优化一点.
#include<cstdio>
typedef long long ll;
const ll mod=1e18+7;
ll qmul(ll a,ll b,ll mod){
ll ans=0;
while(b>0){
if(b&1) ans=(ans+a)%mod;
a=(a+a)%mod;
b>>=1;
}
return ans;
}
void exgcd(ll a,ll b,ll &x,ll &y){
if(b==0){
x=1,y=0;
return ;
}
exgcd(b,a%b,y,x);
y-=a/b*x;
}
int main(){
ll a[100],b[100];
ll k;
scanf("%lld",&k);
ll res=0,M=1;
for(int i=0;i<k;i++)
scanf("%lld",&a[i]);
for(int i=0;i<k;i++){
scanf("%lld",&b[i]);
M*=b[i];
}
for(int i=0;i<k;i++) a[i]=(a[i]%b[i]+b[i])%b[i];
for(int i=0;i<k;i++){
ll mm=M/b[i],x,y;
exgcd(mm,b[i],x,y);
x=(x%b[i]+b[i])%b[i];
res=(res+qmul(qmul(mm,x,M),a[i],M))%M;
}
printf("%lld\n",(res%M+M)%M);
return 0;
}
m不互质的情况:扩展中国剩余定理
洛谷P4777
#include<cstdio>
typedef long long ll;
const int maxn=1e5+10;
ll qmul(ll a,ll b,ll mod){
ll ans=0;
while(b>0){
if(b&1) ans=(ans+a)%mod;
a=(a+a)%mod;
b>>=1;
}
return ans;
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0){
x=1;y=0;return a;}
ll gcd=exgcd(b,a%b,x,y);
ll tp=x;
x=y; y=tp-a/b*y;
return gcd;
}
int main(){
ll a[maxn],b[maxn];
ll n;
scanf("%lld",&n);
for(int i=0;i<n;i++)
scanf("%lld%lld",&b[i],&a[i]);
ll M=b[0],ans=a[0];//第一组特判
for(int i=1;i<n;i++){
ll x,y,c=(a[i]-ans%b[i]+b[i])%b[i];
ll gcd=exgcd(M,b[i],x,y);
if(c%gcd!=0) return -1;//无解情况
x=qmul(x,c/gcd,b[i]/gcd);
ans+=x*M;
M*=b[i]/gcd;
ans=(ans%M+M)%M;
}
printf("%lld",ans);
return 0;
}