扩展中国剩余定理(模数不互质)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 100005
ll r[N],p[N];
ll a1,a2,n1,n2;
int nn;
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0) { x=1; y=0; return a; }
ll d=exgcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
ll mul(ll a,ll x,ll mod)
{
ll ans=0,m=0;
if(x<0) m=1,x=-x;
while(x)
{
if(x&1) ans=(a+ans)%mod;
x=x>>1;
a=(a+a)%mod;
}
if(m)
return -ans;
return ans;
}
int main()
{
scanf("%d",&nn);
scanf("%lld%lld",&p[1],&r[1]);
//r1是前i-1个方程的解
ll r1=r[1],lcm=p[1];//一边使用n次exgcd 一边求lcm
for(int i=2;i<=nn;i++)
{
ll x,y;
scanf("%lld%lld",&p[i],&r[i]);//输入顺序
ll c=(r[i]-r1);//式子右边
ll g=exgcd(lcm,p[i],x,y);
x=mul(x,c/g,p[i]);//龟速乘 防止模数较大 一乘就爆long long
r1+=x*lcm;//求出一个可行的x 更新前i个方程的解
lcm=lcm/g*p[i];//lcm是前i个p[i]的最小公倍数 所以要/g
r1=(r1%lcm+lcm)%lcm;//防止为负数 保证r1是最小的解
}
printf("%lld
",r1);
}
/*
3
11 6
25 9
33 17
*/
普通中国剩余定理:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n;
ll m[15],M=1,a[15];
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0) { x=1; y=0; return a; }
ll d=exgcd(b,a%b,x,y);
ll z=x; x=y; y=z-(a/b)*y;
return d;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld%lld",&m[i],&a[i]);//有时候int*int会爆long long 所以一定记得开
M*=m[i];
}
ll ans=0;
for(int i=1;i<=n;i++){
ll aa=M/m[i],b=m[i],x,y;
ll d=exgcd(aa,b,x,y);
//求一个x使得:mi*x (=) 1 (%m[i])
//这样左右两边同时*a[i]时就满足第i个方程了
ans=(ans+M/m[i]*x*a[i] +M) %M;//防止加爆
}
printf("%lld
",(ans+M) %M);
}
/*
3
3 1
5 1
7 2
*/