中国剩余定理
一、孙子剩余定理怎么来的(百度百科)
孙子定理是中国古代求解一次同余式组(见同余)的方法。是数论中一个重要定理。又称中国余数定理。一元线性同余方程组问题最早可见于中国南北朝时期(公元5世纪)的数学著作《孙子算经》卷下第二十六题,叫做“物不知数”问题,原文如下:
有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?即,一个整数除以三余二,除以五余三,除以七余二,求这个整数。《孙子算经》中首次提到了同余方程组问题,以及以上具体问题的解法,因此在中文数学文献中也会将中国剩余定理称为孙子定理。
二、什么是孙子剩余定理(百度百科)
用现代数学的语言来说明的话,中国剩余定理给出了以下的一元线性同余方程组:
有解,并且通解可以用如下方式构造得到:
设
是整数m1,m2, ... ,mn的乘积,并设
是除了mi以外的n- 1个整数的乘积。设
为
模
的数论倒数(
为
模
意义下的逆元)
方程组
的通解形式为
是整数m1,m2, ... ,mn的乘积,并设
证明:
从假设可知,对任何
,由于
,所以
这说明存在整数
使得
这样的
叫做
模
的数论倒数。考察乘积
可知:
所以
满足:
这说明
就是方程组
的一个解。另外,假设
和
都是方程组
的解,那么:
而
两两互质,这说明
整除
. 所以方程组
的任何两个解之间必然相差
的整倍。
而另一方面,
是一个解,同时所有形式为:
的整数也是方程组
的解。所以方程组所有的解的集合就是:
三、实现
#include<stdio.h> #include<stdlib.h> #define FORa(i,s,e) for(int i=s;i<=e;i++) #define FORs(i,s,e) for(int i=s;i>=e;i--) using namespace std; const int T=1000; int t,w[T+1],b[T+1],n=1,ans; int Exgcd(int a,int b,int &x,int &y) { int ret,temp; if(!b) { x=1,y=0; return a; } ret=Exgcd(b,a%b,x,y); temp=x; x=y; y=temp-a/b*y; return ret; } int main() { int x,y; scanf("%d",&t); FORa(i,1,t) scanf("%d%d",&w[i],&b[i]),n*=w[i]; FORa(i,1,t) { int m=n/w[i]; Exgcd(w[i],m,x,y); ans=(ans+y*b[i]*m)%n; } if(ans>0) printf("%d",ans); else printf("%d",ans+n); return 0; } /*3 3 2 5 3 7 2*/