LightOJ - 1306 - 扩展欧几里得

Ax + By + C = 0,已知\(x \in[x1,x2], y \in [y1,y2]\)
求解的个数

求出一组特解之后,$$x = \frac{c}{d}x_0 + k\frac{b}{d},\ \ y = \frac{c}{d}y_0 - k\frac{a}{d} \ \ (k \in Z)$$求出k的范围即可
\(x1 ≤ x + k\frac{b}{d} ≤x2\)
\(d * b > 0:(x1 - x) \frac{d}{b}≤k≤(x2 - x)\frac{d}{b}\)
\(d*b < 0:(x2 - x) \frac{d}{b} ≤k≤(x1 - x)\frac{d}{b}\)
同理对于y
\(y1 ≤y - k\frac{d}{a}≤y2\)
\(d * a>0:(y - y2)\frac{d}{a} ≤k≤(y - y1) \frac{d}{a}\)
\(d * a<0:(y - y1)\frac{d}{a} ≤k≤(y - y2) \frac{d}{a}\)
特判\(a = 0,b = 0,c = 0\)\(a = 0,b != 0\)\(a != 0,b = 0\)

#include <iostream>
#include <cstdio>
#include <cmath>
#define ll long long
using namespace std;
void ex_gcd(ll a, ll b, ll &d, ll &x, ll &y){
    if(b == 0){
        d = a, x = 1, y = 0;
        return;
    }
    ex_gcd(b, a % b, d, y, x);
    y -= x * (a / b);
}
void solve(ll a, ll b, ll c, ll x1, ll x2, ll y1, ll y2){
    ll d, x, y;
    ex_gcd(a, b, d, x, y);
    if(a == 0 && b == 0){
        if(c == 0)printf("%lld\n", (x2 - x1 + 1) * (y2 - y1 + 1));
        else printf("0\n");
        return;
    }
    if(a == 0){
        ll tmp = c / b;
        if(tmp >= y1 && tmp <= y2 && c % b == 0)
            printf("%lld\n", x2 - x1 + 1);
        else printf("0\n");
        return;
    }
    if(b == 0){
        ll tmp = c / a;
        if(tmp >= x1 && tmp <= x2 && c % a == 0)
            printf("%lld\n", y2 - y1 + 1);
        else printf("0\n");
        return;
    }
    if(c % d != 0){
        printf("0\n");
    }else{
        x = c / d * x, y = c / d * y;
        ll k, t_x1, t_x2, t_y1, t_y2;
        if(d * b > 0){
            t_x1 = ceil((x1 - x) * 1.0 * d / b);
            t_x2 = floor((x2 - x) * 1.0 * d / b);
        }else{
            t_x1 = ceil((x2 - x) * 1.0 * d / b);
            t_x2 = floor((x1 - x) * 1.0 * d / b);
        }
        if(d * a > 0){
            t_y1 = ceil((y - y2) * 1.0 * d / a);
            t_y2 = floor((y - y1) * 1.0 * d / a);
        }else{
            t_y1 = ceil((y - y1) * 1.0 * d / a);
            t_y2 = floor((y - y2) * 1.0 * d / a);
        }
        ll l = max(t_x1, t_y1), r = min(t_x2, t_y2);
        printf("%lld\n", max(0ll, r - l + 1));
    }
}
int main(){
    int t;
    scanf("%d", &t);
    for(int i = 1; i <= t; i++){
        ll a, b, c, x1, x2, y1, y2;
        scanf("%lld%lld%lld", &a, &b, &c);
        scanf("%lld%lld%lld%lld", &x1, &x2, &y1, &y2);
        printf("Case %d: ", i);
        solve(a, b, -c, x1, x2, y1, y2);
    }
    return 0;
}
posted @ 2020-05-26 21:01  Emcikem  阅读(152)  评论(0编辑  收藏  举报