现在的位置: 首页 > 综合 > 正文

POJ 1061 青蛙的约会

2019年04月08日 ⁄ 综合 ⁄ 共 1173字 ⁄ 字号 评论关闭

大意不再赘述。

思路:看过奥运会跑步比赛的都知道,一人在前,一人在后,两个人可以相遇的话,要么一个人可以追上另一个人,要么一个人落后另一个人n圈。

反之,不能相遇的话,在题目中的理解就是,一个人不能永远超过另一个人n圈或者是速度相等(ax一定不等于by)。

在这题中,我们以纬度的长度L为参照物,如果青蛙A在时间T可以相遇青蛙B的话,那么有x + m*T - y - n*T = p*L或者是 y + n*T - x - m*T = pL;  p∈Z。

如何去求解这个方程呢?我们可以把未知数放一边,已知数放一边,即:(n-m)*T - p*L = x-y

有了这个方程,我们就可以把(n-m)看做已知数a,L看做已知数b, 即求解方程:a*T - p*b = c;

注意,我们最终的目的是求T。这个方程我们也不好求解,于是再变为:a*T - p*b = gcd(a, b);

求解方程我们可以通过扩展欧几里得算法来求解,我们可以求出一组解(T0, p0)满足方程的值,如果要求最小的一组(T,p)的值得话,我们可以这样去写:

T *= (ax-by)/d;

T = (T%b1+b1)%b1;

为什么可以这样?介绍两个引理:

1、设a, b, c为任意整数。若方程ax+by = c的一组整数解为(x0,y0),则它的任意整数解都可以写成(x0+k*b', y0-k*a'),其中a' = a/gcd(a,b),b' = b/gcd(a, b),k取任意整数。

2、设a, b, c,为任意整数,g = gcd(a, b),方程ax+by = g的一组解是(x0, y0),则当c是g的倍数时 ax + by = c的一组解是(x0c/g, y0c/g);当c不是g的倍数时不整数解。

为什么可以这样留给大家思考。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;

typedef long long LL;

LL ax, by;
LL n, m;
LL L;

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

void solve()
{
	LL d, x, y;
	ex_gcd(n-m, L, d, x, y);
	LL b1 = L / d;
	if((ax-by) % d || m == n)  { printf("Impossible\n"); return ;} //无整数解或者跳跃的距离相同。 
	x *= (ax-by) / d;
	LL ans = (x % b1 + b1) % b1;
	printf("%lld\n", ans);
}

int main()
{
	while(~scanf("%lld%lld%lld%lld%lld", &ax, &by, &m, &n, &L))
	{
		solve();
	}
	return 0;
}

抱歉!评论已关闭.