1.孙子问题
最早,在《孙子算经》中有这样一个问题:“今有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二,问物几何?用白话描述就是,现在有一个数不知道是多少,只知道这个数除以3余2,除以5余3,除以7余2, 问这个数是多少?
上面的问题可以转换为以下这样一个方程组:
其中这个x就是我们要求的数。而中国剩余定理就是用来解决上述形式的方程组的x解的。
2.中国剩余定理公式
设正整数m1,m2,....,mk两两互素,则同余方程组:
3.解决例题
AcWing 204 表达整数的奇怪方式
解题思路:
代码如下:
#include<iostream>
using namespace std;
typedef long long ll;//防止数据溢出
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b)
{
x=1,y=0;
return a;
}
ll d=exgcd(b,a%b,y,x);
y-=a/b*x;
return d;
}//扩展欧几里得算法
int main()
{
int n;
cin>>n;
bool flag=true;//有无最小的x值
ll a1,m1;
cin>>a1>>m1;
for(int i=0;i<n-1;i++)
{
ll a2,m2;
cin>>a2>>m2;
ll k1,k2;
ll d=exgcd(a1,a2,k1,k2);//求最大公约数
if((m2-m1)%d)//如果m2-m1不是a1,a2的最大公约数的倍数
{
flag=false;
break;
}
k1*=(m2-m1)/d;//由于m2-m1对于最大公约数d扩大了n倍,所以k1也需要扩大
ll t=a2/d;
k1=(k1%t+t)%t;//本题是求最小值x,所以求出最小的k1值
m1=a1*k1+m1;//用m1来表示当前的x的值
a1=abs(a1/d*a2);//求出a1,a2的最小公倍数
}
if(flag) //如果存在就输出最小的x值
cout<<(m1%a1+a1)%a1<<endl;
else
puts("-1");
return 0;
}