省选NOI-专题[数论][excrt][exgcd]:P4777 【模板】扩展中国剩余定理(EXCRT)
我这里推荐一下我的博客
在博客里观看更美观哦~
题目
华丽的分割线
解析
本题解由欧几里得求gcd和同余的性质去推导exgcd,crt,excrt
同余方程及性质
形如
若
对于一个同余方程
则
扩展欧几里得
对于
只要解决
因为
可得到
递归即可求出不定方程的一组整数解,也就求出了同余方程的一个解
方程的通解
已知
设
则有
因为
则
所以方程通解为
我再提一下对于
则对于同余方程组的解
因为对于任意模数
但在第
则方程最小正整数解为
扩展中国剩余定理
当
设我们把前
两式相减得
则
所以合并之后模数为
2个变一个,3个变一个,以此类推,将
模数处理
对于上述
则
对于新的答案,应用新模数
在乘法运算中会爆龟速乘
代码
#include<cstdio>
#define ll long long
using namespace std;
void read(int &x)
{
x=0;
int f;
f=1;
char c;
c=getchar();
while((c<'0'||c>'9')&&c!='-')
{
c=getchar();
}
if(c=='-')
{
f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
x=(x<<3)+(x<<1)+(c^48);
c=getchar();
}
x=x*f;
}
void read(ll &x)
{
x=0;
ll f;
f=1;
char c;
c=getchar();
while((c<'0'||c>'9')&&c!='-')
{
c=getchar();
}
if(c=='-')
{
f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
x=(x<<3)+(x<<1)+(c^48);
c=getchar();
}
x=x*f;
}
ll mul(ll a,ll b,ll p)
{
ll ans=0,x=a;
while(b!=0)
{
if(b&1)
{
ans=(ans+x)%p;
}
x=(x+x)%p;
b>>=1;
}
return (ans%p+p)%p;
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
else
{
ll d;
d=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return d;
}
}
ll a[110000],m[110000];
int main()
{
int n,i;
read(n);
for(i=1;i<=n;i++)
{
read(m[i]);
read(a[i]);
}
ll M=m[1],ans=a[1];
for(i=2;i<=n;i++)
{
ll e,x,d,y,nowm,newm;
e=a[i]-ans;
d=exgcd(M,m[i],x,y);
nowm=m[i]/d;
x=(x%nowm+nowm)%nowm;
x=(mul(x,((e/d)%nowm+nowm)%nowm,nowm)+nowm)%nowm;
newm=M*nowm;
ans=(ans+mul(x,M,newm)+newm)%newm;
M=newm;
}
printf("%lld",ans);
}