【题目描述】
大圣在佛祖的手掌中。
我们假设佛祖的手掌是一个圆圈,圆圈的长为 nn,逆时针记为:0,1,2,⋯,n−1,而大圣每次飞的距离为 d。现在大圣所在的位置记为 x,而大圣想去的地方在 y。要你告诉大圣至少要飞多少次才能到达目的地。
【输入】
有多组测试数据。
第一行是一个正整数 T,表示测试数据的组数;
每组测试数据包括一行,四个非负整数,分别为如来手掌圆圈的长度 n,筋斗所能飞的距离 d,大圣的初始位置 x 和大圣想去的地方 y。
注意孙悟空的筋斗云只沿着逆时针方向翻。
【输出】
对于每组测试数据,输出一行,给出大圣最少要翻多少个筋斗云才能到达目的地。如果无论翻多少个筋斗云也不能到达,输出 Impossible
。
【输入样例】
2 3 2 0 2 3 2 0 1
【输出样例】
1 2
【提示】
数据范围与提示:
对于全部数据,2<n<10^9,0<d<n,0≤x,y<n。
想了很久,才把每一步都给搞明白了
已知n,d,x,y分别是每圈长度,每次能飞的距离,起始点,终点。
那么可以根据题意列出它们之间的关系为: ,其中k1和k2是变量
整理可得:
自然联想到裴蜀定理:若,则一定有解,否则一定无解(k是倍数)
因此首先要判断y-x能否整除gcd(n,d)
若不能整除那一定无解,若是可以整除,则我们需要找到合乎题意的k1使得翻滚次数最少
但是要注意的一点是:若gcd(n,d)不恰好等于y-x而是y-x的倍数,我们就要把最小公约数d乘以倍数
由裴蜀定理可得:所有解的表达式一定是
也就是说,得到一个k1之后,需要与k2/d取模才能得到正确的结果
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
LL exgcd(LL a, LL b, LL &x, LL &y)
{
if (!b)
{
x = 1, y = 0;
return a;
}
LL d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
int main()
{
int T;
scanf("%d", &T);
while (T -- )
{
LL n, d, x, y, a, b;
cin>>n>>d>>x>>y;
int gcd = exgcd(n, d, a, b);
if ((y - x) % gcd) puts("Impossible");
else
{
b *= (y - x) / gcd;
n /= gcd;
printf("%lld\n", (b % n + n) % n);
}
}
return 0;
}