カエルの交際POJ1061

オスのカエルは最初はxの位置にあり、メスのカエルはyの位置にあります。オスのカエルは毎回mメートルジャンプし、メスのカエルは毎回nメートルジャンプし、すべて右にジャンプします。地球の子午線の長さはLで、地球は丸い、つまりL、L + 1、L + 2にジャンプします...実際には、0、1、2にジャンプします。オスのカエルはメスのカエルを追いかけたくて、何回一緒にジャンプできるか尋ねました。彼らが決して会うことができないならば、不可能を出力してください(とても貧しいです!) 

明らかに、x + k *m≡y+ k * n(mod L)となるようなkを要求するだけですよね?少なくとも私はそれを落としたいです!次に、方程式を単純化すると、(nm)*k≡xy(mod L)になります。この場合、この式は実際には(nm)* k + L * s = xyと同等です。これは、整数xのax + by = cのモデルです。

ax + by = cの整数x解を求めるのはそれほど簡単ではありません。そうしないと、一晩中過ごす必要がなくなります。まず、d = gcd(a、b)とし、方程式の両辺をdで割って、a / d * x + b / d * y = c / dを取得します。明らかに、aはdで割り切れ、bもdで割り切れます。 dで割り切れる。xとyは整数の解であるため、c / dも整数である必要があります。cがdを除算しない場合、もちろん不可能です。それ以外の場合、ax0 + by0 = dの解x0とy0を見つけることができれば、両側にc / dを掛けます。つまり、a(c / d * x0)+ b(c / d * y0)= c、元の方程式x =(c / d * x0)、y =(c / d * y0)の解を得ることができます。

ちょっとちょっとちょっと待ってください、ax0 + by0 = dが解決策を持っている必要があることをどうやって知っていますか?これは厳密に証明する必要があります。

定理1:d = gcd(a、b)の場合、正または負の整数kおよびlを見つける必要があるため、d = a * k + b * lとなります。

証明 gcd(a、0)= aなので、b≠0と仮定して、次のように書くことができます。

a = b * q1 + r1

b = r1 * q2 + r2

r1 = r2 * q3 + r3

……

 最初の式から、r1 = a-q1 * bであるため、r1はk1 * a + l1 * b(この場合、k1 = 1、l1 = -q1)の形式で記述できます。2番目の式から、r2 = b-r1 * q2 = b-(k1 * a + l1 * b)* q2 = -q2 * k1 * a +(1-q2 * l1)* b = k2 * a + l2 * b。

明らかに、このプロセスは、式rn = k * a + l * b、つまりd = k * a + l * bが得られるまで、この一連の剰余を通して繰り返すことができます。これは、証明したいことです。

 

したがって、ax0 + by0 = dには解が必要です!では、x0とy0はどのように見つける必要がありますか?拡張ユークリッドと呼ばれるアルゴリズムを使用するには(NND、初めて聞いたのですが、まだ弱すぎます~~~)!

解決策は次のとおりです。gcd(a、b)= gcd(b、a%b)(これを証明する必要はありませんよね?誰もがこれを知っています!)、x0  + b y0  = gcd( a、b)= gcd(b、a%b)= bx1 +(a%b)y1、およびa%bはaa / b * bと書くことができます(a / b * bはaと等しくありません!覚えておいてくださいこのSBの問題について叱られます〜)、したがって= bx1 +(aa / b * b)y1 = a y1  + b (x1-a / b * y1)、したがって、gcd(b、a%b)= bx1が見つかった場合+(a%b)y1のx1とy1の場合、観測によりx0 = y1、y0 =(x1-a / b * y1)を見つけることができます。x1とy1をどのように見つけますか?もちろん、同じ方法でx2とy2を要求することです。gcd(an、0)= an * xn + 0 * ynになるまで質問を続け、xn = 1、yn = 0に設定すると、xn-1とyn-1、xn-2とyn-が見つかります。 2、そしてx0とy0を探しています。

したがって、ax0 + by0 = gcd(a、b)を取得して、整数x0およびy0の拡張ユークリッドアルゴリズムを見つけます(ここでは非常に煩わしいです!このステップをほとんどあきらめました!弱い、弱い、55555 ~~〜)

long long extgcd(long long a, long long b, long long &x, long long &y)
{
    long long d, t;
    if (b == 0) { x = 1; y = 0; return a; }
    d = extgcd(b, a % b, x, y);
    t = x - a/b*y; x = y; y = t;
    return d;
}

 

長い長い?なぜ長いのですか?私はintを使って間違った答えを出したからです!次に、Baidu検索により、long longが存在することがわかりました。つまり、intは32ビットであり、long longは64ビットであり、より大きな整数を表すことができます。この質問は嫌です、なぜあなたは私をいじめているのですか?しかし、その後、x0とy0を見つけることができます。

次に、ax + by = cを見つけ、dで割り切れない場合はcが不可能であると判断します。それ以外の場合は、x = c / d * x0としてx解を取得します。

しかし、ax + by = cを満たす解は無数にあります。神の馬はどうですか?ax + by = cは実際にはax≡c(mod b)と同等ですよね?特別な解x *を取得した場合でも、a(x * + k * b)= ax * + a * k *b≡c+0≡c(mod b)であるため、bを数回加算してもこの方程式の解になります。 )。したがって、方程式は[0、b-1]に整数解を持たなければなりません(0未満の場合、bを数回加算すると、0〜b-1に保つことができます。b-1より大きい場合、 、bを数回引くと、0〜b-1)も保持されます。

では、最小の非負の整数xを見つける方法は?さらに2つの定理が使用されます。

定理2:gcd(a、b)= 1の場合、方程式ax≡c(mod b)は[0、b-1]に対して一意の解を持ちます。

証明:定理1から、a * k + b * l = gcd(a、b)= 1となるような正または負の整数kおよびlを常に見つけることができます。つまり、ax≡1(mod b)を見つけることができます。 x0。もちろん、両側にcを掛けると、a(cx0)≡c(mod b)になるため、x = cx0はax≡c(mod b)の解になります。bを数回加算または減算することがこの方程式の解であるため、xは[0、b-1]の解を持ちます。では、その独自性をどのように判断するのでしょうか。最終的にそれを証明するのに1時間かかりました。証明方法は、x1とx2が両方とも[0、b-1]の解であると仮定すると、ax1≡c(mod b)、ax2≡c(mod b)があります。 、2つの式を引くと、a(x1-x2)≡0(mod b)になります。つまり、a(x1-x2)はbで割り切れる可能性があります。しかし、gcd(a、b)= 1!したがって、aとbの間に通信するための共通言語がないため、(x1-x2)はbで割り切れるとしか言えません。ただし、x1とx2は両方とも[0、b-1]にあるため、x1-x2も[0、b-1]にあるため、x1-x2 = 0としか言えないため、x1 = x2となります。これは理解の独自性を証明しています!

この定理は、定理3を証明するためのものです。定理3は、次のような王様の方法です。

定理3:gcd(a、b)= dの場合、方程式ax≡c(mod b)は[0、b / d-1]で一意の解を持ちます。

証明:前述のように、このくそった方程式はax + by = cと同等です。解があり、両側がdで除算される場合、a / d * x + b / d * y = c / dがあります。はa / d *x≡c/ d(mod b / d)であり、明らかにgcd(a / d、b / d)= 1であるため、定理2から、xは[0、b / dで一意の解を持つことがわかります。 -1]。したがって、ax + by = cのxは[0、b / d-1]で一意の解を持ちます。つまり、ax≡c(mod b)は[0、b / d-1]で一意の解を持ちます。証明してください!

上記のくそった定理で、XiaoCaiはついに最小の非負の整数の問題を解決しました。ax≡c(mod b)の特定の解Xを取得した場合、r = b / gcd(a、b)と設定すると、xは[0、r-1]で一意の解を持つことがわかっているので、次を使用します。 x =(X%r + r)%rは、最小の非負の整数解xを見つけることができます!(X%rは負の値である可能性があり、この時点では[-(r-1)、0]にとどまり、正の値は[0、r-1]にとどまります。rを追加して[1、 2r-1]であるため、モジュロrは[0、r-1]になります。

非常に多くの証明と非常に多くの単語で、21行のコードだけが交換されました。人生は短すぎる!ACM、あなたを愛することは簡単ではないと言いたいです!以下に決定的にコードを投稿してください。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

#include <iostream>

using namespace std;

long long extgcd(long long a, long long b, long long &x, long long &y)

{

    long long d, t;

    if (b == 0) { x = 1; y = 0; return a; }

    d = extgcd(b, a % b, x, y);

    t = x - a / b * y; x = y; y = t;

    return d;

}

int main()

{

    long long x, y, m, n, L, X, Y, d, r;

    while (cin >> x >> y >> m >> n >> L)

    {

        d = extgcd(n - m, L, X, Y); r = L / d;

        if ((x - y) % d) cout << "Impossible" << endl;

        else cout << ((x - y) / d * X % r + r) % r << endl;

    }

    return 0;

}

おすすめ

転載: blog.csdn.net/qq_40596572/article/details/104881733