sgu106 求直线在某一矩形范围内经过的整点,扩展gcd
sgu106 求直线在某一矩形范围内经过的整点,扩展gcd
Description
There is an equation ax + by + c = 0. Given a,b,c,x1,x2,y1,y2 you must determine, how many integer roots of this equation are satisfy to the following conditions : x1<=x<=x2, y1<=y<=y2. Integer root of this equation is a pair of integer numbers (x,y). |
Input
Input contains integer numbers a,b,c,x1,x2,y1,y2 delimited by spaces and line breaks. All numbers are not greater than 108 by absolute value。
Output
Write answer to the output.
Sample Input
1 1 -3 0 4 0 4
Sample Output
4
题意:求解ax+bx+c=0在[x1,x2][y1,y2]经过的整点个数。
思路:扩展gcd解出一个特解,再根据[x1,x2][y1,y2]解出两个k的范围,取交集即可。一个细节,先取交集再取整WA,先取整再取交集就过了,不知为何。。一个技巧,对取整数闭区间可以对两个double边界,下界向上取整ceil,上界向下取整floor,即可取到整数边界的闭区间。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<vector> #include<stack> #include<queue> #include<set> #include<map> #include<string> #include<math.h> #include<cctype> #define ll long long #define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) #define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t)) #define PII pair<int,int> #define fst first #define snd second #define MP make_pair #define PB push_back #define RI(x) scanf("%d",&(x)) #define RII(x,y) scanf("%d%d",&(x),&(y)) #define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z)) #define DRI(x) int (x);scanf("%d",&(x)) #define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y)) #define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d",&(x),&(y),&(z)) #define RS(x) scanf("%s",s) #define RSS(x,y) scanf("%s%s",x,y) #define DRS(x) char x[maxn];scanf("%s",x) #define DRSS(x,y) char x[maxn],y[maxn];scanf("%s%s",x,y) #define MS0(a) memset((a),0,sizeof((a))) #define MS1(a) memset((a),-1,sizeof((a))) #define MS(a,b) memset((a),(b),sizeof((a))) #define ALL(v) v.begin(),v.end() #define SZ(v) (v).size() using namespace std; const int maxn=1000100; const int INF=(1<<29); const double EPS=0.0000000001; const double Pi=acos(-1.0); ll exgcd(ll a,ll b,ll &x,ll &y) { if(b==0){ x=1;y=0; return a; } ll r=exgcd(b,a%b,x,y); ll t=y; y=x-a/b*y; x=t; return r; } int main() { ll a,b,c,x1,x2,y1,y2,x,y; while(cin>>a>>b>>c>>x1>>x2>>y1>>y2){ c=-c; if(a==0&&b==0) if(c==0) cout<<(x2-x1+1)*(y2-y1+1)<<endl; else cout<<0<<endl; else if(a==0) if(c%b==0&&y1<=c/b&&c/b<=y2) cout<<x2-x1+1<<endl; else cout<<0<<endl; else if(b==0) if(c%a==0&&x1<=c/a&&c/a<=x2) cout<<y2-y1+1<<endl; else cout<<0<<endl; else{ ll d=exgcd(a,b,x,y); if(c%d) cout<<0<<endl; else{ x*=c/d;y*=c/d; double L1=(x1-x)*1.0*d/b,R1=(x2-x)*1.0*d/b; if(L1>R1) swap(L1,R1); double L2=(y-y1)*1.0*d/a,R2=(y-y2)*1.0*d/a; if(L2>R2) swap(L2,R2); ll Ld1=ceil(L1),Rd1=floor(R1); ll Ld2=ceil(L2),Rd2=floor(R2); ll L=max(Ld1,Ld2),R=min(Rd1,Rd2); if(L>R) cout<<0<<endl; else cout<<R-L+1<<endl; } } } return 0; }
没有AC不了的题,只有不努力的ACMER!