题目概述
题目描述
给出a,b,c,x1,x2,y1,y2a,b,c,x1,x2,y1,y2a,b,c,x1,x2,y1,y2,求满足ax+by+c=0ax+by+c=0ax+by+c=0,且x∈[x1,x2],y∈[y1,y2]x\in[x1,x2],y\in[y1,y2]x∈[x1,x2],y∈[y1,y2]的整数解有多少对。
输入格式
第一行包含7个整数,a,b,c,x1,x2,y1,y2a,b,c,x1,x2,y1,y2a,b,c,x1,x2,y1,y2,整数间用空格隔开。
输出格式
输出整数解有多少对。
数据范围
对于30%的数据,a,b,c,x1,x2,y1,y2a,b,c,x1,x2,y1,y2a,b,c,x1,x2,y1,y2的绝对值不超过1000。
对于100%的数据,a,b,c,x1,x2,y1,y2a,b,c,x1,x2,y1,y2a,b,c,x1,x2,y1,y2的绝对值不超过10810^8108。
分析
首先ax+by+c=0ax+by+c=0ax+by+c=0可以化为ax+by=−cax+by=-cax+by=−c,这是不是很熟悉?没错,用Exgcd就可以求出一个特解(x0,y0)(x_0,y_0)(x0,y0)。先判断有无解,即(−c)mod  gcd(a,b)(-c)\mod gcd(a,b)(−c)modgcd(a,b)是否等于0,等于0有解,否则无解。至于通解,如下:
{x=x0+t×bdy=y0−t×ad \begin{cases} x=x_0+t\times\dfrac{b}{d}\\\\ y=y_0-t\times\dfrac{a}{d}\\ \end{cases} ⎩⎪⎪⎨⎪⎪⎧x=x0+t×dby=y0−t×da
其中ttt为参数。然后可以根据通解,分别求出ttt在xxx满足条件时的范围,在yyy满足条件时的范围,取交集即可。不过细节和特判挺多的,比如a=0,b=0,c=0a=0,b=0,c=0a=0,b=0,c=0时的情况,以及除法的精度损失等。的确是一道数论好题。
代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
typedef long long LL;
LL a,b,c,xl,xr,yl,yr;
LL Exgcd(LL a,LL b,LL &x,LL &y) {
if (b==0) {
x=1;
y=0;
return a;
}
LL d=Exgcd(b,a%b,x,y);
LL t=x;
x=y;
y=t-a/b*y;
return d;
}
int main() {
scanf("%lld%lld%lld%lld%lld%lld%lld",&a,&b,&c,&xl,&xr,&yl,&yr);
if (xl>xr||yl>yr) {
printf("0");
return 0;
}
if (a==0&&b==0) {
if (c!=0) printf("0");
else printf("%lld",(xr-xl+1)*(yr-yl+1));
return 0;
}
LL x,y,d,k;
d=Exgcd(a,b,x,y);
c=-c;
k=c/d;
x*=k;
y*=k;
if (c%d) {
printf("0");
return 0;
}
if (a==0) {
if (yl<=y&&y<=yr) printf("1");
else printf("0");
return 0;
}
if (b==0) {
if (xl<=x&&x<=xr) printf("1");
else printf("0");
return 0;
}
//通解
//x=x0+t*b/d
//y=y0-t*a/d
/*
(xl-x0)*(d/b)<=t<=(xr-x0)*(d/b)
*/
/*
(yl-y0)*(d/a)<=t<=t(yr-y0)*(d/a)
*/
LL t1l,t1r,t2l,t2r,tl,tr,bb,aa;
bb=b/d;
aa=a/d;
t1l=(xl-x)/bb;
t1r=(xr-x)/bb;
t2l=(y-yl)/aa;
t2r=(y-yr)/aa;
if (x+t1l*bb<xl) t1l++;//除法的精度损失
else if (x+t1l*bb>xr) t1l--;
if (x+t1r*bb<xl) t1r++;
else if (x+t1r*bb>xr) t1r--;
if (y-t2l*aa<yl) t2l--;
else if (y-t2l*aa>yr) t2l++;
if (y-t2r*aa<yl) t2r--;
else if (y-t2r*aa>yr) t2r++;
if ((x+t1l*bb<xl)||(x+t1l*bb>xr)
||(x+t1r*bb<xl)||(x+t1r*bb>xr)
||(y-t2l*aa<yl)||(y-t2l*aa>yr)
||(y-t2r*aa<yl)||(y-t2r*aa>yr)) {
printf("0");
return 0;
}
if (t1l>t1r) swap(t1l,t1r);
if (t2l>t2r) swap(t2l,t2r);
tl=max(t1l,t2l);
tr=min(t1r,t2r);
if (tl>tr) printf("0");
else printf("%lld",tr-tl+1);
return 0;
}
259



被折叠的 条评论
为什么被折叠?



