《孙子算经》中有“物不知数”问题:“今有物不知其数,三三数之余二 ,五五数之余三 ,七七数之余二,问物几何?”答为“23”。
--------这个就是传说中的“中国剩余定理”。 其实题目的意思就是,n % 3 = 2, n % 5 = 3, n % 7 = 2; 问n是多少?
那么他是怎么解决的呢?
看下面:
题目中涉及 3, 5,7三个互质的数、
令:5 * 7 * a % 3 = 1; --------------> a = 2; 即5 * 7 * 2 = 70;
3 * 7 * b % 5 = 1; --------------> b = 1; 即3 * 7 * 1 = 21;
3 * 5 * c % 7 = 1; --------------> c = 1; 即3 * 5 * 1 = 15;
为什么要使余数为1:是为了要求余数2的话,只要乘以2就可以,要求余数为3的话,只要乘以3就可以!
( 因为题目想要n % 3 =2, n % 5 =3, n % 7 =2; )
那么:要使得n % 3 = 2,那么( 5 * 7 * 2 )*2 % 3 = 2;( 因为5 * 7 * 2 % 3 = 1 )
同理: 要使得n % 5 = 3,那么( 3 * 7 * 1 )*3 % 5 = 3;( 因为3 * 7 * 1 % 5 = 1 )
同理:要使得n % 7 = 2,那么( 3 * 5 * 1 )* 2 % 7 = 2;( 因为3 * 5 * 1 % 7 = 1 )
那么现在将( 5 * 7 * 2 )* 2和( 3 * 7 * 1 )* 3和( 3 * 5 * 1 )* 2相加会怎么样呢?我们知道
( 5 * 7 * 2 )* 2可以被5和7整除,但是%3等于2
( 3 * 7 * 1 )* 3可以被3和7整除,但是%5等于3
( 3 * 5 * 1 )* 2可以被3和5整除,但是%7等于2
那么即使相加后,%3, %5,%7的情况也还是一样的!
那么就得到一个我们暂时需要的数( 5 * 7 * 2 )* 2 +( 3 * 7 * 1 )* 3 +( 3 * 5 * 1 )* 2 = 233
但不是最小的!所有我们还要 233 % ( 3 * 5 * 7 ) == 23 得解!
倒推:
a1 = 3, b1 = 2;
a2 = 5, b2 = 3;
a3 = 7, b3 = 2;
假如x符合题目的条件,即x%ai = bi, 求最小的x;
N = a1*a2*.....an;
设Ni对ai求余结果为1,即
N1 = 70 = 5 * 7 * k1(k1为任意整数), N1 % a1 == 1;
N2 = 21 = 3 * 7 * k2(k2为任意整数), N2 % a2 == 1;
N3 = 15 = 3 * 5 * k3(k3为任意整数), N3 % a3 == 1;
即Ni = a1 * a2 *......ai-1 * ai+1*......an * ki;
根据Ni % ai * ki == bi来确定ki的值
x = ((N1*b1) + (N2*b2) + .....+ (Nn*bn)) % N;
转换后为Ni = N / ai * ki;(ki 为任意整数)①
又因为Ni = ai * kki + 1;(kki为任意整数)②
将①和②联立计算得N / ai * ki + (-ai * kki) == 1 == gcd (N/ai, -ai);③
根据③式可以求出最小的ki,将所有Ni相加对N取余即可得出结果x;
void China () { LL sum = 1, ans = 0, x, y, m; for (int i=0; i<n; i++) sum *= a[i]; for (int i=0; i<n; i++) { m = sum / a[i]; biggcd (m, a[i], x, y);///扩展欧几里得 ans = (ans + m*x*b[i]) % sum; } if (ans < 0) ans += sum; printf ("%lld\n", ans); }