POJ 1061
题目链接:
题意:
A从x出发,每次走m步;B从y出发,每次走n步,两人走的总步数需要余L。问至少走多少步才能相遇,不能相遇则输出Impossible
思路:
解不定方程版题。
不定方程,即ax + by = c,a、b、c为常数,x、y为变量。求其中整数解。
定理:ax + by = c’的所有c’中,得到最小的c’是gcd(a,b),详见算法导论。
故求解方案有之,即根据ax + by = gcd(a,b)得出x0和y0。 假设c % gcd(a,b) == 0,则有答案x = x0 * (c / gcd(a,b)),y = y0 * (c / gcd(a,b))。
需要注意原始a和b的正负问题,根据题目具体分析。
源码:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
#define gcd(a,b) __gcd(a,b)
#define LL long long
LL exceed_gcd(LL a, LL b, LL &x, LL &y)
{
if(b == 0){
x = 1;
y = 0;
return a;
}
LL d = exceed_gcd(b, a%b, x, y);
LL tx = y, ty = x - a / b * y; ///关键部分,不能把y前置为a*y/b
// printf("tx = %I64d, ty = %I64d, a = %I64d, b = %I64d\n", tx, ty, a, b);
x = tx, y = ty;
return d;
}
int main()
{
LL t1, t2, t3, n, m, L;
while(scanf("%I64d%I64d%I64d%I64d%I64d", &t1, &t2, &m, &n, &L) != EOF){
LL a, b, x, y;
a = n - m;
b = L;
t3 = t1 - t2;
if(a < 0){
a = -a;
t3 = -t3;
}
while(t3 < 0)
t3 += L;
t3 %= L;
LL d = exceed_gcd(a, b, x, y);
if(t3 % d == 0){
LL ans = x * (t3 / d) % (b / d);
if(ans < 0)
ans += b / d;
printf("%I64d\n", ans);
}
else{
printf("Impossible\n");
}
}
return 0;
}
修改版
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
#define gcd(a,b) __gcd(a,b)
#define LL long long
LL exceed_gcd(LL a, LL b, LL &x, LL &y)
{
if(a < 0){
return exceed_gcd(-a, -b, x, y);
}
if(b == 0){
x = 1;
y = 0;
return a;
}
LL d = exceed_gcd(b, a%b, y, x);
y -= a / b * x; ///注意此处x不能前置为 x * a / b
return d;
}
int main()
{
LL t1, t2, c, n, m, L;
while(scanf("%I64d%I64d%I64d%I64d%I64d", &t1, &t2, &m, &n, &L) != EOF){
LL a, b, x, y;
a = n - m;
b = L;
c = t1 - t2;
LL d = exceed_gcd(a, b, x, y);
if(c % d == 0){
LL ans = x * (c / d) % (b / d); ///本题的特殊处理
if(ans < 0)
ans += b / d;
printf("%I64d\n", ans);
}
else{
printf("Impossible\n");
}
}
return 0;
}