POJ 2115 C Looooops 【扩展欧几里得】

版权声明:如需转载,记得标识出处 https://blog.csdn.net/godleaf/article/details/83065308

题目链接:http://poj.org/problem?id=2115

需要注意的有几点:

第一: exgcd (a, b, x, y) ; 起初以为 y 的最小正整数解是  y = (y % a + a) % a;但事实上最小正整数解是  int tmp = a / gcd (a, b);

y = (y % tmp + tmp) % tmp;

第二: 如果题目要求的是x,表达式最好这样设   ax - by = c ; 如果要求的是 y ,表达式最好这样设  by - ax = c;这样可以避免一些正负号的麻烦;

#include <iostream>
#include <cstdio>
#include <cmath>

using namespace std;

typedef long long ll;

void exgcd (ll a, ll b, ll &x, ll &y) {
	if (!b) {
		x = 1; y = 0; return;
	} else {
		exgcd (b, a % b, y, x); y -= x*(a/b);
	}
} 

ll gcd (ll a, ll b) {
	return !b ? a : gcd (b, a % b);
}

// (A + a*C) % 2^k == B
// A + a*C - B = b*2^k
//  y*C - x*2^k = (B-A)

int main (void)
{
	ll A, B, C, k;
	while (scanf ("%lld%lld%lld%lld", &A, &B, &C, &k) != EOF) {
		if (!A && !B && !C && !k) break;
		ll c = B-A, g = gcd (1ll<<k, C);
		if (c % g) printf ("FOREVER\n");
		else {
			ll x, y;
			exgcd (1ll<<k, C, x, y);
			y *= (c/g);
			y = (y%((1ll<<k)/g) + (1ll<<k)/g) % ((1ll<<k)/g);
			printf ("%lld\n", y);
		}
	}
	return 0;
 } 

猜你喜欢

转载自blog.csdn.net/godleaf/article/details/83065308