线性同余方程组-中国剩余定理or合并方程

线性同余方程组

完整代码见https://github.com/YIWANFENG/Algorithm-github

即若干个线性同余方程的组合。

求解方式可以参考我们普通的方程组,先解式1,将式1的通解带入式2后化简,再解式2,如此重复即可得满足所有式子的解。

例如 


以上适合笔算,但是在程序中表述一般解法,就需要用到等式合并或者中国剩余定理

线性方程组解法与推理

方法一,合并线性同余方程

以下为推导,红色圈出部分为编码时所用的结论。


Code:
//////////////////////////////////////////////////
//		合并方程求解线性同余方程组 
//////////////////////////////////////////////////
void linear_congruences2(int a,int b,int n){
	//求得 ax = b (mod n) 
	if(b % gcd(a,n) == 0){
		int x,y,d,c,re;
		if (n>a) {
			c = a;
			a = n;
			n = c;
			d = gcdEx(a,n,x,y); 
			re = y*b/d;
			cout<<"通解"<<re<<" + Z*"<<a/d<<endl;
		} else {
			d = gcdEx(a,n,x,y); 
			re = x*b/d;
			cout<<"通解"<<re<<" + Z*"<<n/d<<endl;
		}	
	} else {
		cout<<("No result")<<endl;
	}
}


void MergeEquations(int a[],int m[],int n) {
	//合并方程求解线性同余方程组 
	//x = a1 (mod m1)
	//x = a2 (mod m2)
	// ...
	//x = a_n (mod m_n)
	int A=a[0],M=m[0],x,y,k1_t;
	for (int i=1;i<n;i++) {
		gcdEx(M,m[i],x,y);
		k1_t = x;
		A = A - M*k1_t*(A-a[i]) / gcd(M,m[i]);
		M = LCM(M,m[i]);
	}
	linear_congruences2(1,A,M);
}


int main(int argc,char* argv[])
{
	int a[] = {2,3,2};
	int n[] = {3,5,7};
	crh(a,n,3);
	cout<<endl;
	MergeEquations(a,n,3);
    cin.get();
    return 0;
}

方法二,中国剩余定理

1.先判断是否有解:
若整数m1,m2,…,m_n其中任意两数互质,则对任意的a1,a2,…,a_n,方程组有解。
这也就限制住使用中国剩余定理来解线性同余方程组必须要满足这条件。
(注意笔算所用例子方程组中等式左边有系数)
2.构造解:
M = m1*m2*m3*…*m_n, M_i = M / m_i  
t_i = (M_i)^-1 是M_i模m_i的数论倒数,即t_i * M_i 同余于 1 (mod m_i)
通解形式为x = a1*t1*M1 +a2*t2*M2 +…+a_n*t_n*M_n+kM  
= kM +\sum_{i=1} ^n a_i*t_i*M_i  K∈Z,
Code:
int linear_congruences(int a,int b,int n){
	//ax = b (mod n)
	if(b % gcd(a,n) == 0){
		int x,y,d,c,re;
		if (n>a) {
			c = a;
			a = n;
			n = c;
			d = gcdEx(a,n,x,y); 
			re = y*b/d;
			
		} else {
			d = gcdEx(a,n,x,y); 
			re = x*b/d;
		}	
		return re ;
	} else {
		return 0; 	//error
	}
}

void crh(int a[],int m[],int n) {
	//中国剩余定理求解线性同余方程组(不判断是否有解)
	int m_product = 1;
	int M[n];
	int t[n];
	int x=0;
	for(int i=0;i<n;i++)
		m_product *= m[i]; 
	for(int i=0;i<n;i++)
		M[i] = m_product / m[i]; 
	for(int i=0;i<n;i++) 
		t[i] = linear_congruences(M[i],1,m[i]);	
	for(int i=0;i<n;i++)
		x +=a[i]*t[i]*M[i];
	cout<<"通解"<<x<<"+"<<"k*"<<m_product; 
}

int main(int argc,char* argv[])
{
	int a[] = {2,3,2};
	int n[] = {3,5,7};
	crh(a,n,3);
    cin.get();
    return 0;
}

Ref

线性同余方程组定义
https://zh.wikipedia.org/wiki/%E7%BA%BF%E6%80%A7%E5%90%8C%E4%BD%99%E6%96%B9%E7%A8%8B
中国剩余定理
https://zh.wikipedia.org/wiki/%E4%B8%AD%E5%9B%BD%E5%89%A9%E4%BD%99%E5%AE%9A%E7%90%86
中国剩余定理推理
https://www.cnblogs.com/ACShiryu/archive/2011/08/06/gcd.html
求解线性同余方程组
http://www.voidcn.com/article/p-ohkhjttg-ka.html

猜你喜欢

转载自blog.csdn.net/hffhjh111/article/details/81063570