[学习笔记]合并线性同余方程

合并线性同余方程

一.问题引入

在做题过程中,我们可能会遇到这样的情况:

\[\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];
}
posted @ 2020-01-12 13:36  clockwhite  阅读(537)  评论(3编辑  收藏  举报