[学习笔记]合并线性同余方程
合并线性同余方程
一.问题引入
在做题过程中,我们可能会遇到这样的情况:
\[\begin{align}
x\equiv r_1(mod\;m_1)\\
x\equiv r_2(mod\;m_2)\\
x\equiv r_3(mod\;m_3)\\
....
\end{align}
\]
要对这些线性同余方程求解,而我们可以通过合并方程解决这种问题。
二.解决方法
先来看看对于单独的两个同余方程。
\[x\equiv r_1(mod\;m_1)\\
x\equiv r_2(mod\;m_2)\\
\]
很显然的,它们可以变为如下两个不定方程。
\[x=k_1*m_1+r_1\\
x=k_2*m_2+r_2\\
\]
联立可得
\[k_1*m_1+r_1=k_2*m_2+r_2\\
k_1*m_1+k_2*m_2=r_2-r_1
\]
所以我们可以用扩展欧几里得算出有关于\(x\)的一个特解\(x_0\),并且我们知道这么几个式子
\[\begin{align}
&x_0=k_1*m_1+r_1\\
&x=k_i*m_1+r_1\\
&k_i=u*\frac{m_2}{gcd(m_1,m_2)}+k_1(u\in Z)\\
&x=u*\frac{m_1m_2}{gcd(m_1,m_2)}+k_1*m_1+r_1\\
&x=u*lcm(m_1,m_2)+x_0
\end{align}
\]
于是我们呢可以变形得到关于x的一个式子
\[x\equiv x_0(mod\;lcm(m1,m2))
\]
于是我们便将两个同余方程合并成了一个
三.代码
#define ll long long
ll Exgcd(ll a,ll b,ll &x,&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 n,right[1000],mod[1000];
ll solve(){
for(int i=1;i<n;++i){
ll a=mod[i],b=mod[i+1],c=right[i+1]-right[i],x,y,zy,zx;
ll d=Exgcd(a,b,x,y);
if(c%d)return -1;
a/=d,b/=d,c/=d;
x=((x*c)%b+b)%b;
mod[i+1]=mod[i]/Exgcd(mod[i],mod[i+1],zx,zy)*mod[i+1];
right[i+1]=((x*mod[i]%mod[i+1]+right[i])%mod[i+1]+mod[i+1])%mod[i+1];
}
return right[n];
}