sgu106 扩展欧几里德

简略题意:
给出 a , b , c x 1 , x 2 , y 1 , y 2 , 问满足 a x + b y + c = 0 x y 的对数有多少。

首先把输入处理成 a x + b y = c 的形式,且 a , b , c 都为 0 或正数。

然后分类讨论 a , b , c 分别是 0 的情况,这些比较简单。

对于 a b 都不是 0 的情况,可以用扩展欧几里德来求出一组特解 x 0 , y 0
易知道通解的 x y 与特解的关系分别对应:
x = x 0 + k b
y = y 0 k a
那么在合法的区间内,满足要求的 k 的个数就是答案。

需要特别注意左端点向上取整,右端点向下取整,并且负数的取整方法和正数不同…

#define others
#ifdef poj
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#endif // poj
#ifdef others
#include <bits/stdc++.h>
#endif // others
//#define file
#define all(x) x.begin(), x.end()
using namespace std;
#define eps 1e-16
const double pi = acos(-1.0);

typedef long long LL;
typedef unsigned long long ULL;
void umax(int &a, int b) {
    a = max(a, b);
}
void umin(int &a, int b) {
    a = min(a, b);
}
int dcmp(double x) {
    return fabs(x) <= eps?0:(x > 0?1:-1);
}
void file() {
    freopen("data_in.txt", "r", stdin);
    freopen("data_out.txt", "w", stdout);
}

namespace solver {
    LL floor(LL x, LL y) {
        if(x >= 0) return x / y;
        return (x - y + 1) / y;
    }
    LL ceil(LL x, LL y) {
        if(x >= 0) return (x + y - 1) / y;
        return x / y;
    }

    LL a, b, c, x1, x2, y1, y2;
    void no_solution() {
        puts("0");
        exit(0);
    }
    void ex_gcd(LL a, LL b, LL &d, LL &x, LL &y) {
        if(b == 0) {
            x = 1, y = 0, d = a;
            return ;
        }
        ex_gcd(b, a%b, d, y, x);
        y -= a/b*x;
    }
    void solve() {

        scanf("%lld%lld%lld", &a, &b, &c);
        c = -c;
        scanf("%lld%lld%lld%lld", &x1, &x2, &y1, &y2);
        if(c < 0) a = -a, b = -b, c = -c;
        if(a < 0) {
            a = -a;
            x1 = -x1, x2 = -x2;
            swap(x1, x2);
        }
        if(b < 0) {
            b = -b;
            y1 = -y1, y2 = -y2;
            swap(y1, y2);
        }
        if(a == 0 && b == 0) {
            if(c == 0) printf("%lld\n", (y2-y1+1)*(x2-x1+1));
            else
                no_solution();
            return ;
        }
        if(a == 0) {
            if(c % b == 0) {
                LL v = c / b;
                if(v <= y2 && v >= y1) cout<<x2-x1+1<<endl;
                else puts("0");
                return ;
            } else
                no_solution();
        }
        if(b == 0) {
            if(c % a == 0) {
                LL v = c / a;
                if(v <= x2 && v >= x1) cout<<y2-y1+1<<endl;
                else puts("0");
                return ;
            } else
                no_solution();
        }

        LL g, x, y;
        ex_gcd(a, b, g, x, y);
        if(c % g) no_solution();
        LL t = c / g;
        x *= t, y *= t;
        a /= g, b /= g;

        LL al = ceil((x1 - x),  b);
        LL ar = floor((x2 - x), b);
        LL bl = ceil((y - y2), a);
        LL br = floor((y - y1), a);
        cout<<max(0LL, min(ar, br) - max(al, bl) + 1)<<endl;
    }
}
//2 2 -6 0 4 0 4
int main() {
//    file();
    solver::solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/meopass/article/details/80199156