http://acm.hust.edu.cn/vjudge/contest/view.action?cid=65432#problem/F
通过题目的数据范围10^8可知需要一个logn级别的算法来解决本题目,那么显而易见应用扩展gcd来解决,写起来可谓是treak多多!
1.扩展gcd算法
LL exGcd(LL a, LL b, LL &x, LL &y){
if(b == 0){
x = 1;
y = 0;
return a;
}
LL gcd = exGcd(b, a%b, y, x);
y -= (a/b)*x;
return gcd;
}
2.如果解的范围不合法,那么返回
3.如果出现不可以使用扩展gcd的情况要单独计算:a == 0 || b == 0 || (a == 0 && b == 0)
4.如果方程没有解,那么返回
X = X0 + t * (b / gcd(a,b))
Y = Y0 - t * (a / gcd(a,b))
5.求解t的范围时a/gcd和b/gcd的符号会干扰不等式的求解,注意求解时的分情况讨论
6.求解 t 的范围时X - X0 / (b / gcd(a,b))会出现多种情况的误差,因此我们等效的做一下调整
while((lx - 1)*b >= x1) lx--;
while(lx * b < x1) lx++;
while((rx + 1)*b <= x2) rx++;
while(rx * b > x2) rx--;
while((ly - 1)*a >= y1) ly--;
while(ly * a < y1) ly++;
while((ry + 1)*a <= y2) ry++;
while(ry*a > y2) ry--;
7.巧妙一步得到合法的t的范围,确定有几组解
AC代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
LL exGcd(LL a, LL b, LL &x, LL &y){
if(b == 0){
x = 1;
y = 0;
return a;
}
LL gcd = exGcd(b, a%b, y, x);
y -= (a/b)*x;
return gcd;
}
int main(){
//freopen("in.txt", "r", stdin);
LL a,b,c,x1,x2,y1,y2;
while(scanf("%I64d%I64d%I64d%I64d%I64d%I64d%I64d",&a,&b,&c,&x1,&x2,&y1,&y2) == 7){
if(x1 > x2 || y1 > y2){
cout << "0" << endl;
continue;
}
if(a == 0 && b == 0){
if(c == 0) printf("%I64d\n", (x2-x1+1) * (y2-y1+1));
else printf("0");
continue;
}
if(a == 0 && b != 0){
if(-c % b == 0){
if((-c/b) >= y1 && (-c/b) <= y2)
printf("%I64d\n", (x2-x1+1));
else printf("0");
}
else printf("0");
continue;
}
if(a != 0 && b == 0){
if(-c % a == 0){
if((-c/a) >= x1 && (-c/a) <= x2)
printf("%I64d\n",(y2-y1+1));
else
printf("0");
}
else printf("0");
continue;
}
c = -c;
LL x,y;
LL gcd = exGcd(a, b, x, y);
if(c % gcd){
cout << "0" << endl;
continue;
}
x *= c/gcd;
y *= c/gcd;
x1 -= x;
x2 -= x;
b /= gcd;
a /= gcd;
if(b < 0){
b = -b;
swap(x1, x2);
x1 = -x1;
x2 = -x2;
}
LL lx = x1/b;
LL rx = x2/b;
while((lx - 1)*b >= x1) lx--;
while(lx * b < x1) lx++;
while((rx + 1)*b <= x2) rx++;
while(rx * b > x2) rx--;
y1 -= y;
y2 -= y;
a = -a;
if(a < 0){
a = -a;
swap(y1, y2);
y1 = -y1;
y2 = -y2;
}
LL ly = y1/a;
LL ry = y2/a;
while((ly - 1)*a >= y1) ly--;
while(ly * a < y1) ly++;
while((ry + 1)*a <= y2) ry++;
while(ry*a > y2) ry--;
printf("%d\n", max(0ll, min(rx,ry) - max(lx,ly) + 1));
}
return 0;
}