题目大意:中文
注释代码:
//引入概念——求解线性不定方程
//求解线性不定方程ax + by = c
//求a、b的最大公约数(Greatest Common Divisor,简称GCD)即d = gcd(a, b),算法为辗转相除法(即欧几里得算法)
//若d能整除c(即c mod d = 0)则表示方程有解,否则误解
//若有解则利用扩展欧几里得算法求解方程的根,步骤为:
//先将方程两边同除以d得到 _ax + _by = _c
//求出该方程的唯一解xx和yy
//最后得到整个线性方程的全解(即解集)
//x = _c * xx + t * _b
//y = _c * yy - t * _a
//t为任意整数
/*
* Problem ID : POJ 1061 青蛙的约会
* Author : Lirx.t.Una
* Language : C++
* Run Time : 0 ms
* Run Memory : 172 KB
*/
#include <stdio.h>
typedef long long llg;
llg
gcd( llg a, llg b ) {//辗转相除法
if ( !b )
return a;
//递归算法
//return gcd( b, a % b );
llg t;
//非递归算法
while ( b ) {
t = b;
b = a % b;
a = t;
}
return a;
}
void
xuclid( llg a, llg b, llg &x, llg &y ) {//extend Euclid
//扩展欧几里得算法
if ( !b ) {
x = 1;
y = 0;
return ;
}
llg t;
xuclid( b, a % b, x, y );//得到bx + ( a % b )y = c的解
//计算公式
t = x;
x = y;
y = t - a / b * y;
}
int
main() {
llg x, y, m, n, l;//两青蛙的起始位置、速度、维度线长
llg a, b, c;//方程系数
llg s, k;//step,步数,绕维度线的圈数
llg d;//最大公约数
llg t;//temporary,临时变量
scanf("%lld%lld%lld%lld%lld", &x, &y, &m, &n, &l);
//待解的线性不定方程为:
//(x + m * s) - (y + n * s) = k * l (k为整数)
//化简后得:
//(n - m) * s + k * l = x - y
//令
a = n - m;
b = l;
c = x - y;
//之后按照公式计算解即可
d = gcd( a, b );
if ( c % d ) {
puts("Impossible");
return 0;
}
a /= d;
b /= d;
c /= d;
xuclid( a, b, s, k );
//由于解必须是正整数,且为最小值,因此需要对解进行修正
t = c * s / b;//使t * b和c * s最接近
s = c * s - t * b;
//由于b = l必定大于0,因此可以直接相加,不必考虑b小于0的情况
if ( s < 0 )
s += b;
printf("%lld\n", s);
return 0;
}
无注释代码:
#include <stdio.h>
typedef long long llg;
llg
gcd( llg a, llg b ) {
if ( !b )
return a;
llg t;
while ( b ) {
t = b;
b = a % b;
a = t;
}
return a;
}
void
xuclid( llg a, llg b, llg &x, llg &y ) {
if ( !b ) {
x = 1;
y = 0;
return ;
}
llg t;
xuclid( b, a % b, x, y );
t = x;
x = y;
y = t - a / b * y;
}
int
main() {
llg x, y, m, n, l;
llg a, b, c;
llg s, k;
llg d;
llg t;
scanf("%lld%lld%lld%lld%lld", &x, &y, &m, &n, &l);
a = n - m;
b = l;
c = x - y;
d = gcd( a, b );
if ( c % d ) {
puts("Impossible");
return 0;
}
a /= d;
b /= d;
c /= d;
xuclid( a, b, s, k );
t = c * s / b;
s = c * s - t * b;
if ( s < 0 )
s += b;
printf("%lld\n", s);
return 0;
}