SGU-106 Die Gleichung (Erweitertes Europa + detaillierte Verarbeitung)

Portal


Thema

给出ax + by + c = 0 ax + by + c = 0a x+b y+c=0 ist eine binäre unbestimmte Gleichung ersten Grades, die{(x, y) ∣ x ∈ [lx, rx], y ∈ [ly, ry]} \ {(x, y) | x \ in [lx, rx] erfüllt. , y \ in [ly, ry] \}{ ( x ,y ) x[ l x ,r x ] ,Y.[ l y ,r y ] } Die Anzahl der Lösungen.

Ideen zur Problemlösung

Ich dachte, ich hätte viele Fragen über die Expansion Europas geschrieben und ich wusste es gut, aber diese Frage traf mich wieder, wa waw a Zweifel am Leben ...

Erstens ist es nicht schwer zu glauben, dass wenn ccc , das auf die rechte Seite der Gleichung verschoben wird, ist immer noch negativ, also sollteccseinc wechselt gleichzeitig das Vorzeichena, ba, ba ,b sollte auch das Vorzeichen ändern, aber zu diesem Zeitpunkta, ba, ba ,Das Vorzeichen von b kann negativ sein. Am Anfang war meine Idee, auf die unabhängigen Variablenx, yx, yzu verweisenx ,y , dh∣ a ∣ (- x) + ∣ b ∣ (- y) = c | a | (-x) + | b | (-y) = ca ( - x )+b ( - y )=c , und nehmen Sie dann das Negativ direkt nach dem Finden der speziellen Lösung. Ist das nicht möglich? Ja, aber nicht in dieser Frage. Die Gründe sind folgende:

Angenommen, wir berücksichtigen nicht a, ba, b , da wir die Anzahl der Lösungen in einem bestimmten Lösungsraum benötigena ,das Symbol von b , dann wird die obige Gleichung inx = c - byax = \ frac {c-by} {a} umgewandeltx=einc - b y, Dies aaEin Post-Sign-Wechsel wirkt sich direkt auf die endgültige Form der allgemeinen Lösung aus. Wenn wir alsoaamöchtenBei einer Negation ist der richtige Weg durch die Umkehrung des Lösungsraums gegeben, d. h. wird[- rx, - lx] [[ - r x ,- L x ] füryyy ist das gleiche.

Nachdem wir die allgemeine Lösung gelöst haben, müssen wir die Anzahl der Lösungen ermitteln, da x, yx, yx ,Die Transformation von y ist das Gegenteil. Es scheint schwierig zu beginnen, aber tatsächlich müssen wir nur diese Ungleichunglx ≤ x 0 + k 1 bgcd (a, b) ≤ rx lx \ leq x_0 + k_1 \ frac {blösen} {gcd (a, b)} \ leq rxl xx0+k1g c d ( a , b )br x findxxx im Lösungsraumk 1 k_1k1Der Wertebereich und dann yyy sk 2 K_2k2Nehmen Sie für den Wertebereich von nur einen Schnittpunkt der beiden. Zu diesem Zeitpunkt müssen Sie erneut aufpassen: Die linke Seite sollte abgerundet und die rechte Seite sollte abgerundet sein. Zeichnen Sie ein Bild, um es zu verstehen.

Es gibt ein spezielles Urteil a = 0, b = 0 a = 0, b = 0ein=0 ,b=Drei Fälle von 0


//
// Created by Happig on 2020/10/30
//
#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>

using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define Vector Point
#define ENDL "\n"
#define lowbit(x) (x&(-x))
#define mkp(x, y) make_pair(x,y)
#define mem(a, x) memset(a,x,sizeof a);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double, double> pdd;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const double dinf = 1e300;
const ll INF = 1e18;
const int Mod = 1e9 + 7;
const int maxn = 2e5 + 10;

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;
}

ll gcd(ll a, ll b) {
    
    
    return b == 0 ? a : gcd(b, a % b);
}

int main() {
    
    
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    //ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    ll a, b, c, lx, rx, ly, ry;
    cin >> a >> b >> c >> lx >> rx >> ly >> ry;
    c = -c;
    if (c < 0) c = -c, a = -a, b = -b;
    if (a < 0) a = -a, swap(lx, rx), lx = -lx, rx = -rx;
    if (b < 0) b = -b, swap(ly, ry), ly = -ly, ry = -ry;
    if (a == 0 && b == 0) {
    
    
        if (c == 0) cout << (rx - lx + 1) * (ry - ly + 1) << endl;
        else cout << 0 << endl;
        return 0;
    } else if (a == 0) {
    
    
        if (c % b == 0 && ly <= c / b && c / b <= ry) cout << rx - lx + 1 << endl;
        else cout << 0 << endl;
        return 0;
    } else if (b == 0) {
    
    
        if (c % a == 0 && lx <= c / a && c / a <= rx) cout << ry - ly + 1 << endl;
        else cout << 0 << endl;
        return 0;
    }
    ll d = gcd(a, b);
    if (c % d) {
    
    
        cout << "0" << endl;
    } else {
    
    
        ll x, y;
        exgcd(a, b, x, y);
        x = x * c / d, y = y * c / d;
        //cout << x << " " << y << endl;
        a /= d, b /= d;
        int l = max(ceil(1.0 * (lx - x) / b), ceil(1.0 * (y - ry) / a)), r = min(floor(1.0 * (rx - x) / b),
                                                                                 floor(1.0 * (y - ly) / a));
        if (r >= l) cout << r - l + 1 << endl;
        else cout << 0 << endl;
    }
    return 0;
}

Ich denke du magst

Origin blog.csdn.net/qq_44691917/article/details/109411788
Empfohlen
Rangfolge