カエルの交際
トピックリンク:ybt金メダルナビゲーション8-6-1 / luogu P1516
一般的なアイデア
リング上のそれぞれの位置で同じ方向にジャンプするものが2つあり、それぞれが毎回特定の距離をジャンプします。
次に、これら2つのものが同じ場所にあるように、ジャンプする必要がある回数を尋ねます。
同じ場所にない場合は、タイトルの要件に従って出力する必要があります。
アイデア
次に、方程式をリストできるかどうかを検討します。
s + mx = t + nx(mod L)s + mx = t + nx(mod \ L)s+m x=t+n x (m o d L )
s、ts、ts 、tは、m、nm、nの2つの開始位置です。m 、nは、2つのものが毎回ジャンプするグリッドの数です。
それを作りましょう:(m − n)x = t − s(mod L)(mn)x = ts(mod \ L)(m−n )x=t−s (m o d L ) 。
これは1つの変数の線形合同方程式であり、2つの変数の線形不定方程式に変換し、拡張ユークリッドを使用してそれを行うことを考えるのは自然なことです。
(m − n)x + L y = t − s(mn)x + Ly = ts(m−n )x+L y=t−s
しかし、条件を持つための解、つまり(m − n)(mn)が必要です。(m−n )およびLLLは互いに素です。
互いに素でない場合、出力は実行可能ではありません。そうでない場合は、引き続き実行します。
次に、左側の互いに素な2つを作成できます。m−ngcd(m − n、L)x +Lgcd(m − n、L)y = t −sgcd(m − n、L)\ dfrac {mn} {\ gcd(mn、L)} x + \ dfrac {L} {\ gcd(mn、L)} y = \ dfrac {ts} {\ gcd(mn、L)}g cd (m−n 、L )m−n個バツ+g cd (m−n 、L )LY=g cd (m−n 、L )t−S
(ここでのLLのため、後でモジュラスを除算することを忘れないでくださいLはLになりますgcd(m − n、L)\ dfrac {L} {\ gcd(mn、L)}g cd (m−n 、L )L、それはモジュラスを意味します)
しかし、拡張ユークリッドはax + by = 1 ax + by = 1ですa x+b y=1、方程式の右辺は1 11ああ。
シンプルなことを、私たちは同じように式の右側を取る1 11、xxを計算しますx、そして右側を後ろに掛ければ、それだけです。
次に、それを取り出して出力できます。
コード
#include<cstdio>
#define ll long long
using namespace std;
ll x, y, m, n, mo;
ll X, Y, a, b, c;
ll GCD(ll x, ll y) {
//普通的求 gcd
if (!y) return x;
return GCD(y, x % y);
}
ll exgcd(ll a, ll &x, ll b, ll &y) {
//扩展欧几里得求 ax+by=1
if (!b) {
x = 1;
y = 0;
return a;
}
ll re = exgcd(b, y, a % b, x);
y -= a / b * x;
return re;//顺便可以求出 gcd,可用可不用
}
int main() {
scanf("%lld %lld %lld %lld %lld", &x, &y, &m, &n, &mo);
//弄出一元线性同余方程,然后转成二元一次不定方程
a = (m - n + mo) % mo;
b = mo;
c = (y - x + mo) % mo;
int gcd = GCD(a, b);//判断是否有解
if (c % gcd != 0) {
printf("Impossible");
return 0;
}
a /= gcd;//把式子化成 ax+by=c 且 a,b 互质的形式
b /= gcd;
c /= gcd;
exgcd(a, X, b, Y);
X = (X % mo + mo) % mo;
printf("%lld", (X * c) % (mo / gcd));//算出答案(记得这里模数不是mo)
return 0;
}