POJ-2891 Strange Way to Express Integers 中国剩余定理
这题是一道非常直接的中国剩余定理的题目,但是这里的不同的给定的几个数不一定是互质的。因此也就不能直接用解中国剩余定理的方法来求了。
我们通过迭代法来求解最后的答案。
设有 x = 1(mod 5)
y = 2(mod 6)
z = 3(mod 7)
那么根据第一个方程我们设 x = 5t+1, 代入到第二个方程 5t+1 = 2(mod 6) ==> 5t -6u = 2-1 左边这个式子就可以用扩展GCD求出t的解,我们知道t的解由两部分组成,一部分是我们解出来的一般解5(必须保证为最小的正整数),此时u等于4,另外的就是加上 k 个 6 / gcd(5, 6)了,那么我们可以得到 t = 5 + 6k,再将这个值代入到第一个式子我们就将得到一个新的表达式,x = 26(mod 30),得到这个式子是非常有用的,首先如果后面还有式子的话,那么我们将这个式子和下一个式子进行求解,如果后面没有了式子,那么我们又注意到由于保证了x为最小的正整数,所以此时令k=0,代入之后的26就是直接满足这两个方程的最小值。
代码如下:
#include <cstdlib> #include <cstdio> #include <cstring> using namespace std; typedef long long int Int64; int N; Int64 ext_gcd(Int64 a, Int64 b, Int64 &x, Int64 &y) { int temp, ret; if (!b) { x = 1, y = 0; return a; } ret = ext_gcd(b, a % b, x, y); temp = x, x = y, y = temp - a/b*y; return ret; } int main() { int flag; Int64 ai, bi, a, b, g, x, y, ret, temp; while (scanf("%d", &N) == 1) { flag = ret = 0; scanf("%lld %lld", &a, &b); for (int i = 2; i <= N; ++i) { scanf("%lld %lld", &ai, &bi); if (flag) { continue; } g = ext_gcd(a, ai, x, y); // 求得特解 x if ((bi - b) % g != 0) { flag = 1; continue; } x *= (bi - b) / g; x %= (ai / g); if (x < 0) { x += ai / g; } b = a * x + b; a = a * ai / g; } if (flag) { puts("-1"); continue; } printf("%lld\n", b); } return 0; }