例1:一個數被3除余1,被4除余2,被5除余4,這個數最小是幾? |
|
先寫出一個兩位數62,接著在62右端寫這兩個數字的和為8,得到628,再寫末兩位數字2和8的和10,得到62810,用上述方法得到一個有2006位的整數:628101123……,則這個整數的數字之和是( )。
(2006-5)÷10=200....1
17+35*200+1=7018
前面的62810數字和為17
后面開始,以“1123581347”為循環節
共循環10次,每次的和為35
最后余1,就加上1
所以結果是17+35*200+1=7018
例子:PKU 1006
因為只有三個數23 28 33 且三個數兩兩互為質數,所以“中國剩余定理”可知
對于每一組輸入數據p, e ,i, d,所求結果為:n = (R1*p + R2*e + R3*i)%21252-d
其中 R1%p=1, R2%e=1, R3%i=1;
R1 = 5544 = 28*33* 6; //28 33 的公倍數中能被23除余1的最小整數
R2 = 14221 = 23*33*19; //23 33 的公倍數中能被28除余1的最小整數
R3 = 1288 = 23*28* 2; //23 28 的公倍數中能被33除余1的最小整數
為了保證結果大于等于1且小于等于21252,結果修正為:n = (R1*p + R2*e + R3*i - d + 21252)%21252,并且如果n為0,則n = 21252為所求。
問題簡單來說就是 a = ai (mod ni) 求未知數a,
以下小結略去證明, 只是對定理作了必要的解釋, 要了解相關定理,可查閱數論資料.
中國余數定理:
設
n=n1*n2...nk, 其中因子兩兩互質.有: a-----(a1,a2,...,ak), 其中ai = a mod ni, 則
a和(a1,a2,...,ak)關系是一一對應的.就是說可以由 a求出(a1,a2,...,ak), 也可以由(a1,a2,...,ak)求出a
推論1:
對于 a=ai (mod ni) 的同余方程,有唯一解
下面說說由(a1, a2, ..., ak)求a的方法:
定義 mi = n1*n2*...nk / ni; ci = mi(mf mod ni); 其中 mi*mf mod ni = 1;
則 a = (a1*c1+a2*c2+...+ak*ck) (mod n) (注:由此等式可求a%n, 當n很大時)
mi*mf mod ni = 1 => mi*mf+ni*y=1;
代碼如下:
#include <cmath>
using namespace std;
const int MAXN = 100;
int nn, a[MAXN], n[MAXN];
int egcd(int a, int b, int &x, int &y) {
int d;
if (b == 0) {
x = 1; y = 0;
return a;
} else {
d = egcd(b, a%b, y, x);
y -= a/b*x;
return d;
}
}
int lmes() {
int i, tm=1, mf, y, ret=0, m;
for (i=0; i<nn; i++) tm *= n[i];
for (i=0; i<nn; i++) {
m = tm/n[i];
egcd(m, n[i], mf, y);
ret += (a[i]*m*(mf%n[i]))%tm;
}
return (ret+tm)%tm;
}