中国剩余定理(孙子定理)的证明和c++求解
来源:互联网 发布:网络工程项目需求分析 编辑:程序博客网 时间:2024/04/30 05:48
《孙子算经》里面的"物不知数"说的是这样的一个题目:一堆东西不知道具体数目,3个一数剩2个,5个一数剩3个,7个一数剩2个,问一共有多少个。
书里面给了计算过程及答案:70*2 + 21*3 + 15*2 -105*2 = 23。
它的计算思路如下:
70是能被5或7整除的数字,但是除以3正好余1。
21是能被3或7整除的数字,但是除以5正好余1。
15是能被3或5整除的数字,但是除以7正好余1。
所以若有数N = 70 * N1 + 21 * N2 + 15 * N3(其中N,N1,N2,N3为正整数),则整数N是符合题目要求的结果(mod3为N1,mod5为N2, mod7为N3)。
我们把N1赋值2,N2赋值3,N3赋值2。
则: N = 70*2 + 21*3 + 15*2 = 233。
但是3,5,7的最小公倍数为105。
所以N + 105*M均为正解。
因此为了求得最小正整数解,我们需要用(N mod 105)也就是23了。
中国剩余定理(西方数学史中的叫法),就是上一题目的一般情况。
设m1,m2...mk是两两互素的正整数,即: gcd(mi, mj) = 1 (其中 i != j, i, j >= 1且 <=k).
则同余方程组:
x ≡ a1(mod m1)
x ≡ a2(mod m2)
... ...
x ≡ ak(mod mk)
存在唯一[m1,m2...mk]使方程成立.
解法同物不知数是一致的.我们可以稍微模仿一下.
唯一的难题就是如何把上面70, 15, 21的求法,对应到一般情况来.
假设: N1, N2, ... ,Nk.就是对应的权值, 满足如下条件:
N1 能够被 m2, m3..., mk整除,但是除以m1正好余1.
N2 能够被 m1, m3..., mk整除,但是除以m2正好余1.
... ...
Nk能够被m1, m2,...,mk-1整除,但是除以mk正好余1.
N1->Nk如果求出来了,那么假设:
x1 = N1*a1 + N2*a2 + ... + Nk*ak就是我们要求的x一个解, 同物不知数一样,我们把x1 mod (m1*m2*...*mk)的结果
就是x的最小整数解,若为负数,则再加上一个m1*m2*...*mk.因为加减整数倍个m1*m2*...*mk所得结果都是x的解.
所以问题只剩下一个,就是求N1, N2,...,Nk.
怎么求呢?我需要先化简一番:
设m = m1*m2*...*mk, L, J为任意整数.
因为Ni能被m1, m2,...,mi-1, mi+1,...,mk整除(其中i+1<k)
因此: Ni = m/mi *L
a和b都是不全为0的正整数,则:
a*x + b*y = gcd(a, b)
存在唯一的x, y使得上面等式成立。
(当然,容易得知,如果,a和b中有负数,那么也是成立的。)
本题中,m/mi相当于a, -mi相当于b, L相当于x, J相当于y。求出L, J就能求出Ni。
代码:
#include <iostream>using namespace std;//参数可为负数的扩展欧几里德定理void exOJLD(int a, int b, int &x, int &y){ //根据欧几里德定理 if(b == 0){//任意数与0的最大公约数为其本身。 x = 1; y = 0; }else{ int x1, y1; exOJLD(b, a%b, x1, y1); if(a*b < 0){//异号取反 x = - y1; y = a/b*y1 - x1; }else{//同号 x = y1; y = x1 - a/b* y1; } }}//剩余定理int calSYDL(int a[], int m[], int k){ int N[k];//这个可以删除 int mm = 1;//最小公倍数 int result = 0; for(int i = 0; i < k; i++){ mm *= m[i]; } for(int j = 0; j < k; j++){ int L, J; exOJLD(mm/m[j], -m[j], L, J); N[j] = m[j] * J + 1;//1 N[j] = mm/m[j] * L;//2 【注】1和2这两个值应该是相等的。 result += N[j]*a[j]; } return (result % mm + mm) % mm;//落在(0, mm)之间,这么写是为了防止result初始为负数,本例中不可能为负可以直接 写成:return result%mm;即可。}int main(){ int a[3] = {2, 3, 2}; int m[3] = {3, 5, 7}; cout<<"结果:"<<calSYDL(a, m, 3)<<endl;}
- 中国剩余定理(孙子定理)的证明和c++求解
- 孙子定理 中国剩余定理
- 中国剩余定理 /孙子定理
- 中国剩余定理(孙子定理)
- 中国剩余定理的证明
- 孙子问题-中国剩余定理
- fzu1402 猪的安家(中国剩余定理/孙子定理)
- 中国剩余定理即孙子定理的五种解法
- 中国剩余定理证明
- 中国剩余定理(也叫孙子定理)
- 中国剩余定理(孙子定理)
- 中国剩余定理(孙子定理)
- 中国剩余定理 即 孙子定理
- 孙子定理(中国剩余定理)
- ACM-韩信点兵【中国剩余定理-孙子定理】
- 中国剩余定理(孙子定理)
- 中国剩余定理(孙子定理)详解
- 中国剩余定理(孙子定理)
- QT4移植到FL2440开发板的详细过程
- 让健康茶来陪你度过这个炎炎的夏日
- LINUX聊天室50问
- Java程序员集合框架面试题
- BackTrack5(BT5)硬盘安装
- 中国剩余定理(孙子定理)的证明和c++求解
- 通用SQL数据库查询语句范例(多表查询)
- Javascript中的自定义类
- oracle 连接配置
- 在html或asp.net中使用FlexPaper
- android am 启动activity service or broadcast及参数传递
- A/B&&http://acm.hdu.edu.cn/showproblem.php?pid=1576
- 汇编学习--7.10--循环
- 取js文件的get参数