CodeForces: The Equation 106.

一、题目简述

       求给定范围中 ax + by + c = 0 的解的个数,a,b是输入,x的范围是[min_x, max_x],y的范围是[min_y, max_y]。
       输入: a, b, c, min_x, max_x, min_y, max_y (他们的范围在【-10^8 ,
10^8】)
       输出: 解的个数

二、分析

       这是一个扩展欧几里得算法的经典题目了,没什么太多要说的,主要思路就是先求出x、y的通解,再求出t的范围即可
1)利用扩展欧几里得算法求出满足如下方程 a * x0 + b * y 0 = gcd 的x0、y0
2)求出特解x, y 使 a * x1 + b * y1 = c
3)解集就出来了 x = x1 + b / gcd * t y = y1 - a / gcd * t
4)根据x,y范围求出t的范围(这个地方小心,解不等式的时候跟a,b的符号有关系)

三、代码实现

#include <stdio.h>  /* for scanf printf */
#include <math.h>   /* for ceil floor */
 
#define YY_DEBUG                0
 
#define min(a, b)               ((a) < (b) ? (a) : (b))
#define max(a, b)               ((a) < (b) ? (b) : (a))
 
long long gcd(long long a, long long b, long long *x_ptr, long long *y_ptr)
{
    long long   d;
 
    if (b == 0) {
        *x_ptr = 1;
        *y_ptr = 0;
 
        return a;
    }
 
    d = gcd(b, a % b, y_ptr, x_ptr);
 
    *y_ptr = *y_ptr - a / b * (*x_ptr);
 
    return d;
}
 
long long find_all_solutions(long long a, long long b, long long c,
                             long long min_x, long long max_x,
                             long long min_y, long long max_y)
{
    long long   q;
    long long   d;
    long long   x, y;
    long long   lx, rx;
    long long   ly, ry;
    long long   l, r;
 
    if (a == 0 && b == 0) {
        if (c) {
            return 0;
        } else {
            return (max_x - min_x + 1) * (max_y - min_y + 1);
        }
    } else if (a == 0) {
        q = c / b;
 
        if (c % a || q < min_y || q > max_y) {
            return 0;
        } else {
            return max_x - min_x + 1;
        }
    } else if (b == 0) {
        q = c / a;
 
        if (c % b || q < min_x || q > max_x) {
            return 0;
        } else {
            return max_y - min_y + 1;
        }
    }
 
    d = gcd(abs(a), abs(b), &x, &y);
    /* |a| * x + |b| * y = d */
 
#if (YY_DEBUG)
    printf("%d * %d + %d * %d = %d (%d)\n", a, x, b, y, a * x + b * y, d);
#endif
 
    if (c % d) {
        return 0;
    }
 
    q = c / d;
 
    x *= q;
    y *= q;
 
    if (a < 0) {
        x *= -1;
    }
 
    if (b < 0) {
        y *= -1;
    }
 
    /* a * x + b * y = d */
 
#if (YY_DEBUG)
    printf("%d * %d + %d * %d = %d (%d)\n", a, x, b, y, a * x + b * y, c);
#endif
 
    if (b < 0) {
        lx = ceil(1.0 * (max_x - x) * d / b);
        rx = floor(1.0 * (min_x - x) * d / b);
    } else {
        lx = ceil(1.0 * (min_x - x) * d / b);
        rx = floor(1.0 * (max_x - x) * d / b);
    }
 
    if (a < 0) {
        ly = ceil(-1.0 * (min_y - y) * d / a);
        ry = floor(-1.0 * (max_y - y) * d / a);
    } else {
        ly = ceil(-1.0 * (max_y - y) * d / a);
        ry = floor(-1.0 * (min_y - y) * d / a);
    }
 
    l = max(lx, ly);
    r = min(rx, ry);
 
#if (YY_DEBUG)
    printf("[%d, %d]\n", l, r);
#endif
 
    if (r < l) {
        return 0;
    }
 
    return r - l + 1;
}
 
int main(void)
{
    int a, b, c;
    int x1, x2;
    int y1, y2;
 
    scanf("%d %d %d", &a, &b, &c);
    scanf("%d %d", &x1, &x2);
    scanf("%d %d", &y1, &y2);
 
    printf("%lld\n", find_all_solutions(a, b, -1 * c, x1, x2, y1, y2));
 
    return 0;
}

PS: 这个代码可以拆一下,将特殊情况拆出去,这样代码更好看!但是我实在被搞得心态炸了,又是数据类型,我保证以后我刷题绝对不使用int.o(╥﹏╥)o

四、其他

题目链接: https://codeforces.com/problemsets/acmsguru/problem/99999/106

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值