一、题目简述
求给定范围中 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