POJ 1061 拓展欧几里德算法

题意

传送门 POJ 1061

题解

青蛙相遇即满足

( x + m × t ) % L = ( y + n × t ) % L (x+m\times t)\%L=(y+n\times t)\%L (x+m×t)%L=(y+n×t)%L

引入变量 z z z 变形为

z × L + ( n − m ) × t = x − y z\times L+(n-m)\times t=x-y z×L+(nm)×t=xy

求变量 z z z t t t 的线性组合是否满足 x − y x-y xy,这即是拓展欧几里德的形式

a x + b y = c ax+by=c ax+by=c

通过拓展欧几里德算法得到 a x + b y = a % b ax+by=a\%b ax+by=a%b 的一组解,则原式的解

x = x × c / ( a % b ) , y = y × c / ( a % b ) x=x\times c/(a\%b),y=y\times c/(a\%b) x=x×c/(a%b),y=y×c/(a%b)

因为 a a a b / g c d ( a , b ) b/gcd(a, b) b/gcd(a,b) 以及 b b b a / g c d ( a , b ) a/gcd(a, b) a/gcd(a,b) 互质,所以配出如下包含 a b ab ab 的等式。

∵ a x + b y + n a b / g c d ( a , b ) − n a b / g c d ( a , b ) = c \because ax+by+nab/gcd(a,b)-nab/gcd(a,b)=c ax+by+nab/gcd(a,b)nab/gcd(a,b)=c
∴ a [ x + n b / g c d ( a , b ) ] + b [ y − n a / g c d ( a , b ) ] = c \therefore a[x+nb/gcd(a,b)]+b[y-na/gcd(a,b)]=c a[x+nb/gcd(a,b)]+b[yna/gcd(a,b)]=c

大括号中的 n n n 取不同值代表了所有可能解,求余 b / g c d ( a , b ) b/gcd(a,b) b/gcd(a,b) 即可求得 x x x 的最小正值(结果为负则加上模)。一开始对取模运算的正负比较纠结,实际上 g c d gcd gcd 无论正负,递归后得到的都是对应的 x x x y y y 值。

#include <cstdio>
#define min(a,b)    (((a) < (b)) ? (a) : (b))
#define max(a,b)    (((a) > (b)) ? (a) : (b))
#define abs(x)    ((x) < 0 ? -(x) : (x))
#define INF 0x3f3f3f3f
#define delta 0.85
#define eps 1e-6
#define PI 3.14159265358979323846
using namespace std;
typedef long long LL;
int x, y, m, n, L;

int extgcd(int a, int b, LL& x, LL& y){
	int d = a;
	if(b != 0){
		d = extgcd(b, a % b, y, x);
		y -= (a / b) * x;
	}
	else x = 1, y = 0;
	return d;
}

void solve(){
	if(m == n){
		printf("Impossible\n");
		return;
	}

	LL x2, y2;
	int a = n - m, b = L, c = x - y, gcd = extgcd(a, b, x2, y2);
	if(c % gcd != 0){
		printf("Impossible\n");
		return;
	}
	x2 *= c / gcd;
	x2 %= (b / gcd);
	printf("%d\n", x2 > 0 ? x2 : x2 + b / gcd);
}

 int main(){
	int t = 0;
	while(~scanf("%d%d%d%d%d", &x, &y, &m, &n, &L)){
		solve();
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值