题意
传送门 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+(n−m)×t=x−y
求变量 z z z, t t t 的线性组合是否满足 x − y x-y x−y,这即是拓展欧几里德的形式
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[y−na/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;
}