同余方程

问题描述

方程组:
\(x \equiv a_1 ( mod\:m_1)\)
\(x \equiv a_2(mod\:m_2)\)
····
\(x \equiv a_k(mod\: m_k)\)
求解x

求解

首先考虑前两个式子
\(x=m_1\cdot y_1+a_1=m_2\cdot y_2+a_2\)
\(m_1y_1-m_2y_2=a_2-a_1\)(有解当且仅当\((m_1,m_2)|a_2-a_1)\)
\(y_1=y_0+\frac{km_2}{(m_1,m_2)}(k\in Z)\)
\(x=m_1y_0+\frac{km_1m_2}{(m_1,m_2)}+a_1\),设\(x'=m_1y_0+a_1\)
\(x=x'+k[m_1,m_2] ([m_1,m_2]为最小公倍数)\)
所以得到新的式子\(x\equiv x'(mod \:[m_1m_2])\)
则原来方程组方程数目减一
以此类推,得到\(x\equiv x'' (mod \:[m_1m_2m_3])\)
继续下去便得到x的解

poj2891
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define ll long long
using namespace std;
const int maxn=10000000+101;
inline ll read(){
	ll x=0,f=1;char ch=getchar();
	for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
	for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
	return x*f;
}
int k;
void exgcd(ll a,ll b,ll &d,ll &x,ll &y){
	if(!b){d=a;x=1;y=0;return ;}
	exgcd(b,a%b,d,x,y);
	ll t=x;x=y;y=t-(a/b)*y;
	return ;
}
int main(){
	while(scanf("%d",&k)!=EOF){
		ll a1=read(),r1=read(),a2,r2;
		bool fa=false;
		for(int i=2;i<=k;i++){
			a2=read();r2=read();
			if(fa)continue;
			ll d,x,y,c=r1-r2;
			exgcd(a2,a1,d,x,y);
			if(c%d){fa=true;continue;}
			x=x*(c/d);
			a1/=d;
			x=(x%a1+a1)%a1;//求最小整数解
			x=(x*a2+r2); 
			a1=a1*a2;
			r1=((x%a1)+a1)%a1;
		}
		if(fa)printf("-1\n");
		else printf("%lld\n",r1);
	}
	return 0;
}

孙子定理

问题描述:

\(m_1,m_2,···,m_k\)是两两互质的k个正整数
方程组:
\(x\equiv a_1(mod \: m_1)\)
\(x\equiv a_2(mod \:m_2)\)
····
\(x\equiv a_k(mod \:m_k)\)
\(M=m_1m_2···m_k,M_i=\frac{M}{m_i},M_i^{'}M_i\equiv 1(mod \: m_i)\)
则解\(x\equiv \sum_{i=1}^{k}M_i^{'}M_ia_i(mod \: M)\)

证明

\(x=u_1a_1+u_2a_2+···+u_ka_k\)
显然要满足方程组,则等价于\(x=M_1v_1a_1+M_2v_2a_2+····+M_kv_ka_k\)
\(v_i=M_i'时,x满足方程组,所以求得解x\)

posted @ 2021-10-10 13:59  I_N_V  阅读(186)  评论(0编辑  收藏  举报