POJ2891 Strange Way to Express Integers
原题传送:http://poj.org/problem?id=2891
求线性同余方程组。
我对线性同余方程组的求解思路是这样的:
假设有同余方程组:
x ≡ r1 (mod a1) (1)
x ≡ r2 (mod a2) (2)
此方程组可转化为:
x ≡ a1 * t + r1 (3)
x ≡ a2 * u + r2 (4)
由(3)、(4)式容易得到 a1 * t + r1 = a2 * u + r2,运用扩展欧几里得求解二元一次方程可得一个解 t = x0,设d = gcd(a1, a2),m0 = a2 / d,那么 t 的剩余系为:x0 + m0,x0 + 2 * m0,…… ,x0 + (d - 1) * m0,那么,归纳为:
t ≡ x0 (mod m0)
也就是
t = m0 * u + x0 (5)
把(5)式代入(3)式得到
x = a1 * (m0 * u + x0) + r1
则 x = a1 * m0 * u + a1 * x0 + r1
好了,令r3 = a1 * x0 + r1,a3 = a1 * m0 * u,将上式换成下面的样子:
x ≡ r3 (mod a3)
这就是(1)、(2)式合并后的式子了,方程组有多条式子,同样的方式一步一步合并下去得到最终的 r 就是所求。
View Code
1 #include <stdio.h> 2 #define LL long long 3 4 void exgcd(LL a, LL b, LL &d, LL &x, LL &y) 5 { 6 if(b == 0) 7 x = 1, y = 0, d = a; 8 else 9 exgcd(b, a % b, d, y, x), y -= x * (a / b); 10 } 11 12 int main() 13 { 14 LL n, i, a1, r1, a2, r2, a, b, c, d, x0, y0; 15 while(scanf("%lld", &n) != EOF) 16 { 17 bool flag = true; 18 scanf("%lld%lld", &a1, &r1); 19 for(i = 1; i < n; i ++) 20 { 21 scanf("%lld%lld", &a2, &r2); 22 a = a1, b = a2, c = r2 - r1; 23 exgcd(a, b, d, x0, y0); 24 if(c % d != 0) 25 flag = false; 26 LL t = b / d; 27 x0 = (x0 * (c / d) % t + t) % t; 28 r1 = a1 * x0 + r1; 29 a1 = a1 * t; 30 } 31 if(!flag) 32 puts("-1"); 33 else 34 printf("%lld\n", r1); 35 } 36 return 0; 37 }