NOIPのシミュレーションテスト7

ゼロバースト試験バースト、GG。

T1:方程式の解

その後、Exgcd、最小ソリューションの価値、およびすべての解決策を見つけます。

しかしExgcdは、指向プログラミングのデータ範囲を忘れる日本語文は少なく、40分には厚いローリング。

文のこの質問は特別であることをあまりにも多くの。

  1. 0特別に注意を払うように宣告
  2. 特殊記号に注意を払うように宣告
  3. 特別な注意は、正の整数解するかどうかを判断する必要があります

一般的に、これは、シンボルの問題について、Exgcdは確かにポジティブであること、それは、負のマークを入れ、反対数を取り、その後、Exgcdをバックに変更することができ、3です。

Exgcdについて、再びそれを証明する必要があります。

既知の不定方程式\(= Cの\によって斧+ ) に必要な条件、最初の推論の名前を覚えていないことで、それはの可解性\((A、B)| C \)

我々は、セット(G =(A、B)\)\を解決するために、\(= G \によってAX +)を

因为\((A、B)=(B、%b)は、%B = A - B * \ lfloor \ FRAC {A}、{B} \ rfloor \) 所以\(BX +( - B * \ lfloorの\のFRAC {A}、{B} \ rfloor)Y = G \)即:\(AY + B(X - \ lfloor \ FRAC {A}、{B} \ rfloorのY)= G \)

解の集合は、元の方程式を得ることができる\( - \ lfloor \ FRAC {A}、{B} \ rfloor Y \ X_1 = Y、X = Y_1)を

そして\(C =キロ\) 式我々乗客の不定側可能\(K \)を与えるために、\(ax_0 by_0 = C + \)を、ここで\(= kx_1 X_0、Y_0 ky_1 = \)

これは、元の方程式の特殊解のセットです。同じ溶液を得るために、私たちは聞かせて(X- + \デルタX、Y + \デルタy軸の\)\を(B(Y_0 + \デルタy軸)= C \ + \デルタX-(X_0)+)\。式を作成するにはバランス、\(デルタY \のデルタX = \の\のB)

したがって、\(デルタX = \ FRAC {B} {G}、デルタY = \ FRAC} {A} {G \の\の\)

Zの$におけるTの\ FRAC {A} {G}、T \ - 式$の元の解x = X_0 +のTの\ FRAC {B} {G}、Y = Y_0有します。

Y 0よりもわずかに大きい得られ、X 0最大Yにより段差に対応したよりもわずかに大きい取得\(\ FRAC {A} { G} \) 次に+1が答えです。

この質問は、調整には余りにも難しいです\(持っている\楽しい\デバッグ!\) エスケープ

#include <bits/stdc++.h>
#define ll long long

ll Exgcd(ll a, ll b, ll &x, ll &y) {
    if (b == 0) {
        x = 1, y = 0; return a;
    }
    ll r = Exgcd(b, a % b, y, x);
    y -= (a / b) * x;
    return r;
}

ll Solve(ll a, ll b, ll c) {
    bool opa = 0, opb = 0;
    if (a == 0 && b == 0) return c == 0 ? -1 : 0;
    if (a == 0) return (c == 0 || (c % b == 0 && c / b > 0)) ? -1 : 0;
    if (b == 0) return (c == 0 || (c % a == 0 && c / a > 0)) ? -1 : 0;
    if (c < 0) a = -a, b = - b, c = -c;
    if (a < 0) a = -a, opa = 1;
    if (b < 0) b = -b, opb = 1;
    ll x, y;
    ll g = Exgcd(a, b, x, y);
    if (c % g != 0) return 0;
    ll t = c / g;       x *= t, y *= t, a /= g, b /= g, c = t;
    if (opa) a = -a, x = -x;
    if (opb) b = -b, y = -y;
    if (a < 0) a = -a, b = -b, c = -c;
    if (a * b < 0) return -1;
    x %= b;
    while (x <= 0) x += b;
    y = (c - a * x) / b;
    if (y < 0) return 0;
    ll y_min = y % a;
    while (y_min <= 0) y_min += a;
    return y_min <= y ? (y - y_min) / a + 1 : 0;
}

signed main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        ll a, b, c;
        scanf("%lld%lld%lld", &a, &b, &c);
        ll ans = Solve(a, b, c);
        if (ans == -1 || ans > 65535) puts("ZenMeZheMeDuo");
        else printf("%lld\n", ans);
    }
}

おすすめ

転載: www.cnblogs.com/gekoo/p/11227861.html