这题写了很久了,也看了许多题解。。可是发现都好复杂,看不懂啊,果然智商是硬伤。
虽然知道这题是扩展欧几里德算法。。但是对与ax+by=c中系数的正负处理的不好,偶然看一题解发现处理的很好就抄袭了过来。Orz大神
http://blog.csdn.net/jerryihuang/article/details/7992068
这道题各种坑啊,各种讨论,各种bug,不过倒是学到不少,至少扩展欧几里德会用了,,,泪啊
//求的是ax+by=gcd(a,b)的解,其中d=gcd(a,b),注意a>b,并且最好把a,b变成正数计算
void exgcd(LL a,LL b,LL &d,LL &x,LL &y) { if(!b){d=a;x=1;y=0;} else{exgcd(b,a%b,d,y,x);y-=x*(a/b);} }
//先算出ax+by=gcd(a,b)的解x1,y1,d=gcd(a,b),然后ax+by=c的一组解是x=x1*c/d,y=y1*c/d;(注意:若c%d!=0,则无解)
//又因为若ax+by=c的一组解为(x0,y0),则它的任意解都可以写成(x0+kb',y0-ka'),其中a'=a/gcd(a,b),b'=b/gcd(a,b),k取任意值
// File Name: 106.cpp // Author: zlbing // Created Time: 2013/2/28 20:19:38 #include<iostream> #include<string> #include<algorithm> #include<cstdlib> #include<cstdio> #include<set> #include<map> #include<vector> #include<cstring> #include<stack> #include<cmath> #include<queue> using namespace std; #define CL(x,v); memset(x,v,sizeof(x)); #define INF 0x3f3f3f3f #define LL long long void exgcd(LL a,LL b,LL &d,LL &x,LL &y) { if(!b){d=a;x=1;y=0;} else{exgcd(b,a%b,d,y,x);y-=x*(a/b);} } int main(){ LL a,b,c,d,x,y,x1,x2,y1,y2; while(~scanf("%I64d%I64d%I64d",&a,&b,&c)) { scanf("%I64d%I64d",&x1,&x2); scanf("%I64d%I64d",&y1,&y2); if(a==0||b==0) { if(a==0&&b){ if(c%b||c/b>y2||c/b<y1)printf("0\n"); else { printf("%I64d\n",x2-x1+1); } } else if(b==0&&a){ if(c%a||c/a>x2||c/a<x1)printf("0\n"); else { printf("%I64d\n",y2-y1+1); } } else { if(c==0)printf("%I64d\n",(y2-y1+1)*(x2-x1+1)); else printf("0\n"); } continue; } if(c<0)c=-c; else{ a=-a;b=-b; } if(a<0){ a=-a; x1=-x1; x2=-x2; swap(x1,x2); } if(b<0){ b=-b; y1=-y1; y2=-y2; swap(y1,y2); } LL d,x,y; if(a<b){ exgcd(b,a,d,y,x); } else exgcd(a,b,d,x,y); if(c%d){ printf("0\n"); continue; } a=a/d; b=b/d; c=c/d; while(x<x1){ x+=b; y-=a; } while(x>x2){ x-=b; y+=a; } LL ans=0; x=x*c;y=y*c; while(x<=x2){ if(ans)break; if(x>=x1&&x<=x2&&y>=y1&&y<=y2)ans++; if(ans)break; x+=b;y-=a; } while(x>=x1){ if(ans)break; if(x>=x1&&x<=x2&&y>=y1&&y<=y2)ans++; if(ans)break; x-=b;y+=a; }
//将x,y暴力加或减,使x,y都在取值区间里 if(ans){ LL a1=(x2-x)/b;LL b1=(y-y1)/a; ans+=min(a1,b1); a1=(x-x1)/b;b1=(y2-y)/a; ans+=min(a1,b1); } printf("%I64d\n",ans); } return 0; }