LUOGU_4777_【模板】扩展中国剩余定理(EXCRT)
注意加快速乘,防止整数溢出。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mx=1e5+5;
int n;
ll a[mx],m[mx];
ll fmul(ll x,ll y,ll z) {
x%=z,y%=z; if(y<0) x=-x,y=-y;
ll sum(0);
for(;y;y>>=1) {
if(y&1) sum=(sum+x)%z;
x=(x+x)%z;
}
return sum;
}
ll fpow(ll x,ll y,ll z) {
x%=z;
ll mul(1);
for(;y;y>>=1) {
if(y&1) mul=mul*x%z;
x=x*x%z;
}
return mul;
}
void exgcd(ll &x,ll &y,ll a,ll b,ll &d) {
if(b==0) {
x=1,y=0,d=a;
}
else {
exgcd(y,x,b,a%b,d);
y-=x*(a/b);
}
}
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%lld%lld",&m[i],&a[i]);
}
bool flg(0);
for(int i=2;i<=n;i++) {
ll tmp=((a[i]-a[1])%m[i]+m[i])%m[i];
ll k1,k2,d; exgcd(k1,k2,m[1],m[i],d);
if(tmp%d) {
flg=1;break;
}
k1=(fmul(k1,tmp/d,m[i]/d)+(m[i]/d))%(m[i]/d);
ll M=m[1]/d*m[i];
a[1]=(a[1]+fmul(m[1],k1,M))%M;
m[1]=M;
}
printf("%lld",a[1]);
}
中国剩余定理:
记
M
=
∏
i
=
1
n
m
i
M=\prod_{i=1}^nm_i
M=∏i=1nmi ,
M
i
=
M
m
i
M_i=\frac{M}{m_i}
Mi=miM ,则
a
n
s
=
∑
i
=
1
n
M
i
M
i
−
1
a
i
ans=\sum_{i=1}^nM_iM_i^{-1}a_i
ans=∑i=1nMiMi−1ai 是模
M
M
M 意义下原同余方程组的解。其中
M
i
−
1
M_i^{-1}
Mi−1 是模
m
i
m_i
mi 意义下的逆元。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mx=1005;
int n;
ll M,res,a[mx],m[mx];
ll fpow(ll x,ll y,ll z) {
x%=z;
ll mul(1);
for(;y;y>>=1) {
if(y&1) mul=mul*x%z;
x=x*x%z;
}
return mul;
}
void exgcd(ll &x,ll &y,ll a,ll b) {
if(b==0) {
x=1,y=0;
}
else {
exgcd(y,x,b,a%b);
y-=x*(a/b);
}
}
int main() {
scanf("%d",&n); M=1;
for(int i=1;i<=n;i++) {
scanf("%lld%lld",&m[i],&a[i]);
M=M*m[i];
}
for(int i=1;i<=n;i++) {
ll mi=M/m[i],x,y;
exgcd(x,y,mi,m[i]); x=(x%m[i]+m[i])%m[i];
res=(res+a[i]*mi*x%M)%M;
}
printf("%lld",res);
}