题目链接。
分析:
数论了解的还不算太多,解的时候,碰到了不小的麻烦。
设答案为x,n = (1<<k), 则 (A+C*x) % n == B
即 (A+C*x) ≡ B (mod n)
化简得 C*x ≡ (B-A) (mod n)
设 a = C, b = (B-A)
则原式变为 ax=b.解 x。
到这里,以为求出来 a 的逆, 然后 x = b*a-1。
a 的 逆好求,用《训练指南》上的模板(P122) inv函数.
例如,求 2 模 66536 下的逆, inv(2, 66536) 便可, 但 inv(LL a, LL n) 这个函数的要求就是如果 a 和 n 的最大公约数不为1,则逆不存在。 但样例是有解的。
在网上查了一下,说是《算法导论》(第三版)P555页有解法, 便根据书上的解法解 x 了。
代码如下:
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <queue> #include <algorithm> #include <cmath> #include <string> #include <map> #include <set> using namespace std; typedef long long LL; void gcd(LL a, LL b, LL &d, LL &x, LL &y) { if(!b) { d = a; x = 1; y = 0; } else { gcd(b, a%b, d, y, x); y-= x*(a/b); } } int main() { LL A, B, C, k, n, x, y, d; while(cin >> A >> B >> C >> k) { if(A == 0 && B == 0 && C == 0 && k == 0) break; n = (1LL << k); LL a = C; LL b = (B-A+n)%n; if(b == 0) { printf("0 "); continue; } gcd(a, n, d, x, y); if(b % d == 0) { LL x0 = (x*(b/d)) % n; LL minn = (x0%(n/d)+n/d)%(n/d); cout << minn << endl; } else printf("FOREVER "); } return 0; }