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

本文深入探讨了扩展欧几里得算法(exgcd)在解决特定数学问题中的应用,特别是如何找到最小正整数解,并给出了代码实现,强调了在不同场景下设置方程的重要性。

题目链接: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;
 } 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值