其他分享
首页 > 其他分享> > 中国剩余定理

中国剩余定理

作者:互联网

《孙子算经》有这么一道题:今有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二,问物几何。
就是说:一些东西,不知道有多少个,三个三个数剩两个,五个五个数剩三个,七个七个数剩两个,问这些东西最少有多少个。
《孙子歌诀》中给出了解法:三人同行七十稀,五树梅花廿一支,七子团圆正半月,除百零五便得知。
思路就是\(5*7=35\),\(35\)的倍数中能模\(3\)等于\(1\)的最小数是\(70\),同理\(3*7\mod{5}=1\),\(3*5\mod{7}=1\),接着\(70*2+21*3+15*2=233\),再将\(233\)模\(105\)得\(23\),最后23就是这些东西的最小个数。
原理:
\(70*2\mod{3}=2\),\(21*3\mod{3}=0\),\(15*2\mod{3}=0\) ==> \((70*2+21*3+15*2)\mod{3}=2\),\((70*2+21*3+15*2)\mod{105}\mod{3}=2\)。
\(70*2\mod{5}=0\),\(21*3\mod{5}=3\),\(15*2\mod{5}=0\) ==> \((70*2+21*3+15*2)\mod{5}=3\),\((70*2+21*3+15*2)\mod{105}\mod{5}=3\)。
\(70*2\mod{7}=0\),\(21*3\mod{7}=0\),\(15*2\mod{7}=2\) ==> \((70*2+21*3+15*2)\mod{7}=2\),\((70*2+21*3+15*2)\mod{105}\mod{7}=2\)。
普遍思路:
\(\left\{\begin{matrix} m\mod a_{1}=b_{1} & & & & \\ m\mod a_{2}=b_{2} & & & & \\ …… & & & & \\ m\mod a_{n}=b_{n} & & & & \end{matrix}\right.\)
设$M=\prod_{i=1}^{n}a_{i} $,
设 $ n_{i} $ 是 \({M\div a_{i}}\) ,且\(n_{i}\mod a_{i}=1\)
最后的答案就是$\sum_{i=1}^{n}n_{i}*b_{i}\mod M $
证明:
\(n_{i}\mod a_{i}=1\) ==> \(n_{i}*b_{i}\mod a_{i}=b_{i}\)
n数组中除\(n_{i}\)外,其余的都可以被\(a_{i}\)整除。
所以\(\sum_{i=1}^{n}n_{i}*b_{i}\mod a_{i}=b_{i}\) ==> \(\sum_{i=1}^{n}n_{i}*b_{i}\mod M\mod a_{i}=b_{i}\)
代码:

#include<iostream>
#define int __int128
using namespace std;
int read(){
	int x=0,f=1;
	char a=getchar();
	while(a<'0'||a>'9'){
		if(a=='-')f=-1;
		a=getchar();
	}
	while(a>='0'&&a<='9'){
		x*=10;
		x+=a-'0';
		a=getchar();
	}
	return x*f;
}
int n;
int a[20],b[20];
void write(int a){
	if(a>9)write(a/10);
	putchar(a%10+48);
}
signed main(){
	n=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
		b[i]=read();
	}
	int cnt=0;
	for(int i=1;i<=n;i++){
		int ans=1;
		for(int j=1;j<=n;j++){
			if(j!=i){
				ans*=a[j];
			}
		}
		int j;
		for(j=1;ans*j%a[i]!=b[i];j++);
		ans*=j;
		cnt+=ans;
	}
	int ji=1;
	for(int i=1;i<=n;i++){
		ji*=a[i];
	}
	cnt%=ji;
	write(cnt);
	return 0;
}

这里的\({n_{i}\div \left ( {M\div a_{i}}\right ) }\)可以用求逆元的方法求。

标签:剩余,15,21,int,定理,70,中国,105,mod
来源: https://www.cnblogs.com/z-2-we/p/16313899.html