1638:五指山
题目描述
大圣在佛祖的手掌中。
我们假设佛祖的手掌是一个圆圈,圆圈的长为 n,逆时针记为:0,1,2,⋯,n−1,而大圣每次飞的距离为 d。现在大圣所在的位置记为 x,而大圣想去的地方在 y。要你告诉大圣至少要飞多少次才能到达目的地。
输入格式
有多组测试数据。
第一行是一个正整数 T,表示测试数据的组数;
每组测试数据包括一行,四个非负整数,分别为如来手掌圆圈的长度 n,筋斗所能飞的距离 d,大圣的初始位置 x 和大圣想去的地方 y。
注意孙悟空的筋斗云只沿着逆时针方向翻。
输出格式
对于每组测试数据,输出一行,给出大圣最少要翻多少个筋斗云才能到达目的地。如果无论翻多少个筋斗云也不能到达,输出 Impossible。
样例
样例输入 #1
2
3 2 0 2
3 2 0 1
样例输出 #1
1
2
样例解释 #1
第一组数据:
- n=3,d=2,x=0,y=2。
- 大圣从 0 出发,每次逆时针飞 2 个单位。
- 飞 1 次:位置 (0+2)mod3=2,到达 y。
- 输出 1。
第二组数据:
- n=3,d=2,x=0,y=1。
- 飞 1 次:到 2,不是 1。
- 飞 2 次:位置 (0+2×2)mod3=4mod3=1,到达 y。
- 输出 2。
数据范围
对于全部数据:
- 2<n<109
- 0<d<n
- 0≤x,y<n
时空限制
- 时间限制:1000 ms
- 内存限制:524288 KB
注意:本题实质是求解线性同余方程。设大圣飞了 t 次,则位置为 (x+d⋅t)modn=y。即:
x+d⋅t≡y(modn)
移项得:
d⋅t≡y−x(modn)
令 a=d, b=y−x,则方程为 at≡b(modn)。要求最小正整数解 t。
解法:
- 计算 g=gcd(a,n)。
- 如果 b 不能被 g 整除,则无解,输出
Impossible。
- 否则,方程两边同除以 g,得到 a′t≡b′(modn′),其中 a′=a/g, b′=b/g, n′=n/g。
- 由于 gcd(a′,n′)=1,用扩展欧几里得算法求 a′ 在模 n′ 下的逆元 inv,则 t≡b′⋅inv(modn′)。
- 最小正整数解为 t=(b′⋅invmodn′+n′)modn′。
注意:b=y−x 可能为负数,需要调整为模 n 下的非负剩余:b=(y−x+n)modn。但直接计算 b=y−x,然后在同余方程中处理负数即可(扩展欧几里得算法允许负数)。
由于 n 可能很大(109),但 T 不会太大(题目未给出,但通常不会很多),扩展欧几里得算法复杂度 O(logn),可以接受。
注意:如果 b=0,即 x≡y(modn),则 t=0 是一个解,但 t=0 表示不飞,题目可能要求至少飞一次?但题目要求“最少要翻多少个筋斗云”,如果初始位置就是目的地,那么 t=0 应该是答案。但样例中没有这种情况。我们输出 0 即可。
另外,注意 d 可能为 0?数据范围 0<d<n,所以 d>0,不会为 0。