POJ2115 C Looooops(数论)

时间:2023-03-08 17:40:24

题目链接

分析:

数论了解的还不算太多,解的时候,碰到了不小的麻烦。

设答案为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 = ; y = ; }
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 == && B == && C == && k == ) break; n = (1LL << k); LL a = C;
LL b = (B-A+n)%n; if(b == ) { printf("0\n"); continue; } gcd(a, n, d, x, y); if(b % d == ) {
LL x0 = (x*(b/d)) % n;
LL minn = (x0%(n/d)+n/d)%(n/d);
cout << minn << endl;
}
else printf("FOREVER\n");
} return ;
}