同余
学习
中国剩余定理
\(ans=\sum_{i=1}^nM_i*r_i*t_i modM\)
其中\(M=\prod_1^nmod_i,M_i=\frac{M}{mod_i},t_i为M_i模M下的逆元\)
void solve()
{
cin>>n;
int M=1;
for(int i=1;i<=n;i++) cin>>mod[i]>>r[i],M=M*mod[i];
int ans=0;
int x,y;
for(int i=1;i<=n;i++)
{
int Mi=M/mod[i];
ex_gcd(Mi,mod[i],x,y);
ans=(ans+(Mi*x%M*r[i]%M)+M)%M;
}
cout<<ans%M<<endl;
}
扩展中国剩余定理
cin>>n;
for(int i=1;i<=n;i++) cin>>mod[i]>>r[i];
int x,y;
for(int i=1;i<n;i++)
{
int a=mod[i],b=mod[i+1],c=r[i+1]-r[i],g=gcd(a,b);
if(c%g) {cout<<-1<<endl;return;}
a/=g,b/=g,c/=g;
ex_gcd(a,b,x,y);
x=(x*c%b+b)%b;//非负最小整数解
mod[i+1]=mod[i]/gcd(mod[i],mod[i+1])*mod[i+1];//mod[i+1]->lcm(mod[i],mod[i+1])
r[i+1]=(mod[i]*x%mod[i+1]+r[i])%mod[i+1];//新的余数 r[i+1]-r[i]= mod[i]*x+mod[i+1]*y
}
//可能在某些题连longlong都会爆,这时候就要用龟速乘
cout<<r[n]<<endl;
扩展欧几里得
对于形如\(ax+by=c\),可以用扩欧求出它的一个特解\((x_0,y_0)\),
判断有解:\(gcd(a,b)|c\)
通解:\((x_0+kb,y_0-ka)\)
当\(x\)最小时,\(y\)取最大,反之亦然。
最小非负整数解:\(x_{min}=(x\%b+b)\%b\),如果要正整数解,则当\(x_{min}=0\)将它改为\(b\)。
\(y\)同理。
模板
代码
int exgcd(int a,int b,int &x,int &y)
{
if(!b) {x=1,y=0;return a;}
int d=exgcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
void solve()
{
cin>>a>>b>>c;
//求解ax+by=c,问题
int x,y;
int d=exgcd(a,b,x,y);
if(c%d) {cout<<-1<<endl;}//无解
else
{
a/=d,b/=d,c/=d;//化简公式
x*=c,y*=c;//因为之前求出的解a*x0+b*y0 = d ,要将解变成c/d倍
x=(x%b+b)%b;//求x的最小非负整数解
y=(c-a*c)/b;
}
}