SGU-106 L'équation (Europe élargie + traitement détaillé)

Portail


Sujet

给出ax + par + c = 0 ax + par + c = 0un x+b y+c=0 est une équation binaire indéfinie du premier degré, qui vérifie{(x, y) ∣ x ∈ [lx, rx], y ∈ [ly, ry]} \ {(x, y) | x \ in [lx, rx] , y \ in [ly, ry] \}{ ( x ,y ) x[ l x ,r x ] ,Oui[ l y ,r y ] } Le nombre de solutions.

Idées de résolution de problèmes

Je pensais avoir écrit beaucoup de questions sur l'expansion de l'Europe et je le savais bien, mais cette question m'a frappé à nouveau, wa waw a douter de la vie ...

Tout d'abord, il n'est pas difficile de penser que si ccc déplacé vers le côté droit de l'équation est toujours négatif, doncccdevrait êtrec change de signe, en même tempsa, ba, bun ,b devrait aussi changer de signe, mais à ce momenta, ba, bun ,Le signe de b peut être négatif. Au départ, mon idée était de faire référence aux variables indépendantesx, yx, yx ,y , c'est-à-dire∣ a ∣ (- x) + ∣ b ∣ (- y) = c | a | (-x) + | b | (-y) = ca ( - x )+b ( - y )=c , puis prenez le négatif directement après avoir trouvé la solution spéciale. N'est-il pas possible de faire ça? Oui, mais pas dans cette question. Les raisons sont les suivantes:

Parce que ce dont nous avons besoin est le nombre de solutions dans un espace de solution donné, supposons que nous ne considérions pas a, ba, bun ,Le symbole de b , alors l'équation ci-dessus est convertie enx = c - byax = \ frac {c-by} {a}X=unec - b y, Ce aaun changement de post-signe affecte directement la forme finale de la solution générale est modifiée, donc si nous voulonsaaune négation, le chemin correct est donné par l'inverse de l'espace de solution, c'est-à-dire devient[- rx, - lx] [[ - r x ,- L x ] pouryyy est le même.

Ensuite, lorsque nous résolvons la solution générale, nous devons obtenir le nombre de solutions, car x, yx, yx ,La transformation de y est l'inverse. Cela semble difficile à démarrer, mais en fait, il suffit de résoudre cette inégalitélx ≤ x 0 + k 1 bgcd (a, b) ≤ rx lx \ leq x_0 + k_1 \ frac {b } {gcd (a, b)} \ leq rxl xX0+k1g c d ( a , b )br x trouverxxx dans l'espace solutionk 1 k_1k1La plage de valeurs, puis yyy 'sk 2 k_2k2Pour la plage de valeurs de, prenez simplement une intersection des deux. À ce stade, vous devez à nouveau faire attention. Le côté gauche doit être arrondi vers le haut et le côté droit doit être arrondi vers le bas. Dessinez une image pour comprendre.

Il y a un jugement spécial a = 0, b = 0 a = 0, b = 0une=0 ,b=Trois cas de 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;
}

Je suppose que tu aimes

Origine blog.csdn.net/qq_44691917/article/details/109411788
conseillé
Classement