Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 20702 | Accepted: 5596 |
Description
for (variable = A; variable != B; variable += C) statement;
Input
Output
Sample Input
3 3 2 16 3 7 2 16 7 3 2 16 3 4 2 16 0 0 0 0
Sample Output
0 2 32766 FOREVER
题意:求解最小的y使得 A + C*y = B (mod 1<<k)。
思路:化简等式 (1<<k)*x + y*C = B-A。当且仅当(B-A) % gcd(1<<k, C) == 0才有解。
令temp = (B-A)/gcd(1<<k, C);
化简——(1<<k)*x/temp + y*C/temp = gcd(1<<k, C);
求出x和y,y *= temp。
由扩展欧几里得 定理三——若gcd(a, b) = d,则方程ax ≡ c (mod b)在[0, b/d - 1]上有唯一解。
求解最小的y时,只需对(1<<k) / gcd(1<<k, C)取余即可。
AC代码:
#include <cstdio> #include <cstring> #include <algorithm> #define LL long long using namespace std; LL A, B, C, k; void exgcd(LL a, LL b, LL &d, LL &x, LL &y) { if(b == 0) {d = a, x = 1, y = 0;} else { exgcd(b, a%b, d, y, x); y -= x * (a / b); } } void solve() { B -= A; LL d, x, y; LL a = (1LL<<k); exgcd(a, C, d, x, y); if(B % d) printf("FOREVER\n"); else { x *= (B / d); y *= (B / d); y = (y % (a / d) + a / d) % (a / d); printf("%lld\n", y); } } int main() { while(scanf("%lld%lld%lld%lld", &A, &B, &C, &k) != EOF) { if(A == 0 && B == 0 && C == 0 && k == 0) break; solve(); } return 0; }