sgu 106
2015-08-16 01:30
357 查看
给出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距离的差值 求结果即可
还可以直接算 思路也是找离矩形框的最近点。但是要同时判断x,y,可能出现x符合条件y不符合条件的情况。不用这么麻烦。。。。卧槽 我就是来卖萌的。。。。
顺便附上 啊mao题解http://www.cnblogs.com/hchlqlz-oj-mrj/p/4729996.html
初始解(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
相关文章推荐
- valid parentheses
- Handler.post()
- 让你不再畏惧线性代数的5个小知识
- Java 杭电ACM Train Problem I 1022
- mysql 自连接查询数据
- 黑马程序员---冒泡排序和选择排序的理解
- 判断素数ISprime
- ZOJ3558 How Many Sets III(公式题)
- gem install mongo
- 接口的使用
- BZOJ 题目2049: [Sdoi2008]Cave 洞穴勘测(link cut tree)
- 旋转链表
- Unity Shader 学习笔记 (五) 积雪效果Shader
- 计算几何题目分类
- Codeforces Round #316 (Div. 2) E. Pig and Palindromes DP
- 修改完文件,想直接切换分支,怎么办???
- 第八篇:关于释放内存(原创+转载长贴)
- ACM ICPC 2013-2014. NEERC. Eastern Subregional Contest
- Objective-C 三大特征
- 又拍云——图像处理师(GraphicsMagick、ImageMagick、FFmpeg)