个人理解---中国剩余定理
2016-03-25 15:55
246 查看
a1 r1 a2 r2 a3 r3
有一个数x,除以3余2,除以5余3, 除以7余2,求x的最小值;
计算过程是:(70 * 2 + 21 * 3 + 15 * 2 ) % 105 = 23.
(N1 * R1 + N2 * R2 + N3 * R3) % N = x.
其中 70(N1)是5(A2)和7(A3)的最小公倍数,对3(A1)求余为1;
21(N2)是3(A1)和7(A3)的最小公倍数,对5(A2)求余为1;
15(N3)是3(A1)和7(A2)的最小公倍数,对5(A3)求余为1;
N 为3(A1),5(A2),7(A3)的最小公倍数.
那么就可以推广到:
x % A1 = R1,
x % A2 = R2,
x % A3 = R3,
x % A4 = R4,
......
x % An = Rn.
求最小的x,其中Ai为素数;
N = A1 * A2 * A3 * A4 * ... * An;
所以我们要求出Ni, Ni=A1 * A2 *...* Ai-1 * Ai+1 *... * An * Ki, 根据Ni%Ai=1来确定Ki的值
x = (R1*N1 + R2*N2 + R3*N3 + ... + Rn*Nn)% N ;因为要求的是:最小整数解,所以对N求余即可;
下面关键就是求Ni,即求Ki;
因为N是所有A的乘积,Ni为除Ai外的所有Ai的倍数,所以:
Ni = N / Ai * K;(K为任意整数);---------式1;
又因为Ni对Ai求余为1,所以:
Ni = Ai * K0 + 1;(K0为任意整数);-------式2;
从上面可以看出只要我们求出K或者K0就可以求出Ni了;
由1,2式得N / Ai * K = Ai * K0 + 1
化简得:(N/Ai)*K + (-Ai)K0 = 1;
不难看出上式满足ax + by = gcd(a, b)
由上面的分析知道N/Ai与-Ai一定互质即gcd(N/Ai, -Ai) = gcd(N/Ai, Ai) = 1;
所以可以用扩展欧几里德来求解K和K0;
有一个数x,除以3余2,除以5余3, 除以7余2,求x的最小值;
计算过程是:(70 * 2 + 21 * 3 + 15 * 2 ) % 105 = 23.
(N1 * R1 + N2 * R2 + N3 * R3) % N = x.
其中 70(N1)是5(A2)和7(A3)的最小公倍数,对3(A1)求余为1;
21(N2)是3(A1)和7(A3)的最小公倍数,对5(A2)求余为1;
15(N3)是3(A1)和7(A2)的最小公倍数,对5(A3)求余为1;
N 为3(A1),5(A2),7(A3)的最小公倍数.
那么就可以推广到:
x % A1 = R1,
x % A2 = R2,
x % A3 = R3,
x % A4 = R4,
......
x % An = Rn.
求最小的x,其中Ai为素数;
N = A1 * A2 * A3 * A4 * ... * An;
所以我们要求出Ni, Ni=A1 * A2 *...* Ai-1 * Ai+1 *... * An * Ki, 根据Ni%Ai=1来确定Ki的值
x = (R1*N1 + R2*N2 + R3*N3 + ... + Rn*Nn)% N ;因为要求的是:最小整数解,所以对N求余即可;
下面关键就是求Ni,即求Ki;
因为N是所有A的乘积,Ni为除Ai外的所有Ai的倍数,所以:
Ni = N / Ai * K;(K为任意整数);---------式1;
又因为Ni对Ai求余为1,所以:
Ni = Ai * K0 + 1;(K0为任意整数);-------式2;
从上面可以看出只要我们求出K或者K0就可以求出Ni了;
由1,2式得N / Ai * K = Ai * K0 + 1
化简得:(N/Ai)*K + (-Ai)K0 = 1;
不难看出上式满足ax + by = gcd(a, b)
由上面的分析知道N/Ai与-Ai一定互质即gcd(N/Ai, -Ai) = gcd(N/Ai, Ai) = 1;
所以可以用扩展欧几里德来求解K和K0;
#include<stdio.h> #define MAXN 22 int n, N0; void ex_gcd(int a, int b, int &x, int &y) { if(b==0) { x = 1; y = 0; return ; } ex_gcd(b, a%b, x, y); int temp = x; x = y; y = temp - a/b * y; if(a*b<0)///如果a和b异号那么x和y取反;理由不太清楚; { x = -x; y = -y; } } int China(int N[], int A[], int R[]) { int x = 0; for(int i=1; i<=n; i++) { int K, K0; ex_gcd(N0/A[i], -A[i], K, K0); N[i] = A[i] * K0 + 1; ///或者 N[i] = N0/A[i] * K; x = (x + N[i] * R[i] + N0) % N0; } return (x+N0)%N0;///防止出现负数; } int main() { int A[MAXN], R[MAXN], N[MAXN]; scanf("%d", &n); N0 = 1; for(int i=1; i<=n; i++) { scanf("%d %d", &A[i], &R[i]); N0 *= A[i]; } int x = China(N, A, R); printf("%d\n", x); return 0; }
相关文章推荐
- 友盟相关
- radio, checkbox,Select的操作
- HA 简单报错总结
- 动态模糊认知图
- MojoliciousLite: 实时的web框架 概述
- Java GC 及HBase RegionServer GC调优
- 1108. Finding Average (20)段错误
- 1.3.2(extra)
- 1.3.3
- 思维导图软件Freemind简介
- Could not open INSTALL.LOG file
- JMeter学习(十一)属性和变量
- MojoliciousLite: 实时的web框架 概述
- MojoliciousLite: 实时的web框架 概述
- 彻底理解字符编码
- c++ 类的使用 友元函数 重载运算符
- 解决oracle高版本的向低版本拷贝数据的方法
- C++的引用的一个测试例子
- 【涨知识】你家用的是A级锁还是B级锁,什么锁最安全?
- 虚拟现实竞争企业分析