给出a,b,c,x1,x2,y1,y2然后你要做的就是找出在矩形框内的整数点有多少个。
初始解(x*(-c)/g,y*(-c)/g)
然后对于x轴方向上的增量是 b/g
我写成几何了 我去 。。。好好的数论题。
先用扩展欧几里德求出初始解,获取到在离矩形框最近的点的x坐标。
然后计算直线和x=x1,x2,y=y1和y2上的点。
然后取中间两个。判断两个点是否都在矩形框上。如果存在一个就判断该点是不是整数点。
都不在就是0。都在就是 x1和x2距离的差值 求结果即可
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <utility>
#include <algorithm>
using namespace std;
typedef long long ll;
ll a,b,c,x1,x2,yy1,y2,flagx,flagy,ans;
const double eps=1e-20;
typedef pair<double,double> P;
P p[5];
bool is()
{
return x1>x2||yy1>y2?0:1;
}
bool isdouble(double x)///判断不是整数 ///加值的范围是多少
{
return (fabs(x-(ll)(x+eps))>eps)?1:0;
}
ll exgcd(ll a,ll b,ll *x,ll *y)
{
if(b==0)
{
*x=1;
*y=0;
return a;
}
ll xx,yy;
ll g=exgcd(b,a%b,&xx,&yy);
*x=yy;
*y=xx-a/b*yy;
return g;
}
double near(double x)
{
return x>0?x+eps:x-eps;
}
int which(P &a,P &b)
{
int answer1=0,answer2=0;
if(!(a.first-x2>eps||x1-a.first>eps||a.second-y2>eps||yy1-a.second>eps)) answer1=1;
if(!(b.first-x2>eps||x1-b.first>eps||b.second-y2>eps||yy1-b.second>eps)) answer2=2;
return answer1+answer2;
}
double length(P &a,double x,double y)
{
return (a.first-x)*(a.first-x)+(a.second-y)*(a.second-y);
}
int main()
{
while(~scanf("%I64d%I64d%I64d%I64d%I64d%I64d%I64d",&a,&b,&c,&x1,&x2,&yy1,&y2))
{
if(!is())
{
printf("0\n"); ///对边界合法性的考虑
continue;
}
ll maxx=max(x1,x2),minx=min(x1,x2);
ll maxy=max(yy1,y2),miny=min(yy1,y2);
if(a==0)///注意是整数点
{
if(b==0)
{
if(c==0) printf("%I64d\n",(abs(x1-x2)+1)*(abs(yy1-y2)+1));
else printf("0\n");
continue;
}
else
{
double ansy=-c*1.0/b;
if(ansy<miny||ansy>maxy||isdouble(ansy)) printf("0\n");
else printf("%I64d\n",abs(x1-x2)+1);
continue;
}
}
else
{
if(b==0)
{
double ansx=-c*1.0/a;
if(ansx<minx||ansx>maxx||isdouble(ansx)) printf("0\n");///可能存在精度问题
else printf("%I64d\n",abs(yy1-y2)+1);
continue;
}
else
{
ans=0,flagx=1,flagy=1;
if(a<0) flagx=-1; ///扩展gcd求值为正值
if(b<0) flagy=-1;
ll x,y;
ll g=exgcd(abs(a),abs(b),&x,&y);
if((-c)%g!=0)
{
printf("0\n");
continue;
}
x=x*(-c)/g*flagx;///增量为 k*b/g;
y=y*(-c)/g*flagy;///增量为 -k*a/g;
p[0].first=x1;
p[0].second=(-c-a*x1)*1.0/b;
p[1].first=x2;
p[1].second=(-c-a*x2)*1.0/b;
p[2].first=(-c-b*yy1)*1.0/a;
p[2].second=yy1;
p[3].first=(-c-b*y2)*1.0/a;
p[3].second=y2;
sort(p,p+4);
int d=which(p[1],p[2]);
if(d==0)
{
printf("0\n");
continue;
}
if(d==1) if(!isdouble(p[1].first)&&!isdouble(p[1].second)) ans=1;///判断整数点
if(d==2) if(!isdouble(p[2].first)&&!isdouble(p[2].second)) ans=1;
if(d==3)
{
if(p[1].first<=x&&x<=p[2].first)
{
ans=abs((ll)near(p[1].first)-x)/abs(b/g)+abs((ll)near(p[2].first)-x)/abs(b/g)+1;
}
else
{
ll ans1=abs((ll)near(p[1].first)-x)/abs(b/g);
ll ans2=abs((ll)near(p[2].first)-x)/abs(b/g);
ans=abs(ans1-ans2);
if(fabs(p[2].first-p[1].first)<eps&&fabs(p[2].second-p[1].second)<eps)
{
if(!isdouble(p[2].first)&&!isdouble(p[2].second)) ans+=1;
}
else
{
double len1=length(p[1],x,y),len2=length(p[2],x,y);
if(len1>len2) {if(!isdouble(p[2].first)&&!isdouble(p[2].second)) ans+=1;}
else if(!isdouble(p[1].first)&&!isdouble(p[1].second)) ans+=1;
}
}
}
printf("%I64d\n",ans);
}
}
}
return 0;
}
还可以直接算 思路也是找离矩形框的最近点。但是要同时判断x,y,可能出现x符合条件y不符合条件的情况。不用这么麻烦。。。。卧槽 我就是来卖萌的。。。。
顺便附上 啊mao题解http://www.cnblogs.com/hchlqlz-oj-mrj/p/4729996.html