1、首先,明确中国剩余定理解决的问题:求解同余方程组未知量N。
2、条件:已知方程组中方程个数k、被除数Mi数组、余数ai数组,且M数组中元素两两互质。
3、解决思路:
由孙子算经中的类似问题,我们得知:N=∑Ni*ai(i:1~k),所以问题的关键便在于求k个Ni。
求解Ni:
设MM=M[1]*M[2]*... ...M[k];
由孙子算经类推得:
①:Ni=1+M[i]*J(设J为任意常数) ②:Ni=MM/M[i]*L(L为任意常数)
所以有:
1+M[i]*J==MM/M[i]*L ===> -J*M[i]+MM/M[i]*L=1;
又因为G(M[i],MM/M[i])==1,所以有同余方程:-J*M[i]+MM/M[i]*L==G(M[i],MM/M[i]),然后扩展欧几里得解该方程,即得J,与L,进而可以求得Ni,最终求得N。
所以实现代码;
int exgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
int gcd=exgcd(b,a%b,x,y);
if(a*b>=0)
{
int temp=x;
x=y;
y=temp-a/b*y;
}
else
{
int temp=x;
x=-y;
y=a/b*y-temp;
}
return gcd;
}
int China(int M[],int a[],int k)
{
int mm=1,ans=0;
int L,J;
for(int i=1;i<=k;++i)mm*=M[i];
for(int i=1;i<=k;++i)
{
exgcd(mm/M[i],-M[i],L,J);
int NTemp=1+J*M[i];
ans+=NTemp*a[i];
}
return (ans%mm+mm)%mm;
}
被除数不互质的情况下
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include<algorithm>
#include <set>
#include <queue>
#include <stack>
#include<vector>
#include<map>
#include<ctime>
#define ll long long
using namespace std;
ll exgcd(ll a,ll b,ll &x,ll &y){
if(b==0)
{
x=1,y=0;
return a;
}
ll q=exgcd(b,a%b,y,x);
y-=a/b*x;
return q;
}
int main(){
ll a1,c1,a2,c2,x,y,t;
ll n;
while(scanf("%lld",&n)!=EOF)//n个式子
{
bool ff=1;
scanf("%lld%lld",&a1,&c1);//第一个方程的被除数和余数
for(ll i=1;i<n;i++)
{
scanf("%lld%lld",&a2,&c2);
ll q=exgcd(a1,a2,x,y);
if((c2-c1)%q)
{
ff=0;
}
t=a2/q;
x=((x*(c2-c1)/q)%t+t)%t;
c1+=a1*x;
a1*=(a2/q);
}
if(ff==0)
{
printf("-1\n");//无解的情况
continue;
}
printf("%lld\n",c1);
}
return 0;
}
The end;