题目描述
大圣在佛祖的手掌中。
我们假设佛祖的手掌是一个圆圈,圆圈的长为 n,逆时针记为:0,1,2,…,n−1,而大圣每次飞的距离为 d。
现在大圣所在的位置记为 x,而大圣想去的地方在 y。
要你告诉大圣至少要飞多少次才能到达目的地。
注意:孙悟空的筋斗云只沿着逆时针方向翻。
输入格式
有多组测试数据。
第一行是一个正整数 T,表示测试数据的组数;
每组测试数据包括一行,四个非负整数,分别为如来手掌圆圈的长度 n,筋斗所能飞的距离 d,大圣的初始位置 x 和大圣想去的地方 y。
输出格式
对于每组测试数据,输出一行,给出大圣最少要翻多少个筋斗云才能到达目的地。
如果无论翻多少个筋斗云也不能到达,输出 Impossible。
关于最后答案自己的理解
import java.util.*;
public class Main {
static long[] a = new long[1], b = new long[1];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
while (t -- > 0) {
long n = sc.nextLong(), d = sc.nextLong(), x = sc.nextLong(), y = sc.nextLong();
long gcd = exgcd(n, d, a, b);
if ((y - x) % gcd != 0) System.out.println("Impossible");
else {
// b[0]为-an + bd = gcd(n,d)的一个解
b[0] *= (y - x) / gcd; // 扩大(y - x) / gcd倍后
// 此时的b[0]为-an + bd = y - x的一个解 ((y - x)是gcd的倍数)
// b的通项公式为: b = b[0] + k * (n / gcd), b表示大圣要翻的筋斗云的次数
// b要取最小且b又得大于0 (总不能往后翻吧2333, 等于0的特例这里暂时不讨论)
// 因此,当b[0]为b[0] / (n / gcd)的余数,且k = 0时,b取到最小值
// 因为n / gcd > 0, k取大于0的数,b会更大,k取小于0的数b会小于0
n /= gcd;
System.out.println((b[0] % n + n) % n);
}
}
}
static int exgcd(long a, long b, long[] x, long[] y) {
if (b == 0) {
x[0] = 1;
y[0] = 0;
return (int)a;
}
int d = exgcd(b, a % b, y, x);
y[0] -= a / b * x[0];
return d;
}
}