C Looooops POJ - 2115

数论好题。。 香!

首先我们看到这一题, 题意是

\[a + c * x \equiv b (mod \ \ 2 ^ k) \]

对此式移一下项, 得

\[c * x \equiv b - a (mod \ \ 2 ^ k) \]

此时原式为标准线性同余方程。
\(exgcd\)解得\(x\)后,x 要做如下处理 :
\(g = gcd(b - a, 2 ^ k), k = 2 ^ k, d = b - a\)
1#. \(x = x * (d / g)\), 此时求得一组特解(因为\(exgcd\)解出的是\(RHS = gcd\)时的解,所以需要乘倍数)
2#. \(x = (x \% (k / g) + k / g) % (k / g)\), 此时求得最小正整数解。
\(\text{TIP : 1. 本题无需开int64 2. 1# 无需加%k}\)

#include <iostream>
#include <cstdio>
#include <cmath>
#define int long long 
using namespace std;
int exgcd(int a, int b, int &x, int &y) {
	if(b == 0) {
		x = 1;
		y = 0;
		return a;
	}
	int g = exgcd(b, a % b, x, y);
	int tmp = x;
	x = y;
	y = tmp - (a / b) * y;
	return g;
}
signed main(){
	
	long long A, B, C, K;
	while (cin >> A >> B >> C >> K) {
		int a = A, b = B, c = C, k = K, x, y;
		x = 0, y = 0;
		if(!a && !b && !c && !k) 
			break;
		k = pow(2, k);
		int d = b - a;
		int g = exgcd(c, k, x, y);
		if(d % g) {
			puts("FOREVER");
		} else {
			x = x * (d / g);
			printf("%lld\n", (x % (k / g) + k / g) % (k / g));
		}
	}
	return 0;
} 
/*
2 4 6 3
11 27 20 5
850 1350 430 11
262135 352675 222524 19
0 0 0 0
*/
posted @ 2019-12-05 22:21  永远_少年  阅读(166)  评论(0编辑  收藏  举报