链接
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2868
题解
这题本身不难,但是边界情况容易造成
我先把坐标读入进来并且乘以
,容易写出直线的一般方程
用字母代替系数,得到直线方程
现在就是要找横纵坐标都是
的倍数的点,其个数就是答案
解不定方程
,
,解的个数就是答案
如果
,方程无解,点数是
否则解
假设解出一组
解集构造为
而
即
解得
利用取整函数求出
的个数就好了
当我在整个不等式中除以
时,我相当于默认了
,但是如果
,这个算法算出的答案就错了
所以这里一定要单独讨论(WA了5发)
代码
//扩展欧几里德
#include <bits/stdc++.h>
#define ll long long
#define eps 1e-8
using namespace std;
ll read(ll x=0)
{
ll c, f=1;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-48;
return f*x;
}
ll gcd(ll a, ll b){return !b?a:gcd(b,a%b);}
void exgcd(ll a, ll b, ll &x, ll &y)
{
if(b==0){x=1, y=0;return;}
ll xx, yy;
exgcd(b,a%b,xx,yy);
x=yy, y=xx-a/b*yy;
}
ll work()
{
ll a, b, c, g, x0, y0, x1, y1, x2, y2;
double l, r, tmp;
scanf("%lf",&tmp), x1=tmp*10;
scanf("%lf",&tmp), y1=tmp*10;
scanf("%lf",&tmp), x2=tmp*10;
scanf("%lf",&tmp), y2=tmp*10;
a=y1-y2, b=x2-x1, c=-x1*y2+x2*y1;
if(b==0)
{
if(x1%10!=0)return 0;
if(y1*y2<0)return abs(y1)/10+abs(y2)/10+1;
return max(abs(y1),abs(y2))/10-min(abs(y1)-1,abs(y2)-1)/10;
}
g=gcd(a,b);
if(c%(10*g)!=0)return 0;
exgcd(10*a,10*b,x0,y0);
l=0.1*(x1-x0*c/g)*g/b;
r=0.1*(x2-x0*c/g)*g/b;
if(l>r+eps)swap(l,r);
return (ll)(floor(r+eps)-ceil(l-eps)+1);
}
int main()
{
ll T=read();
while(T--)printf("%lld\n",work());
return 0;
}