SGU106 - The equation
106. The equation
time limit per test: 0.5 sec.
memory limit per test: 4096 KB
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
题解:运用扩展欧几里得解二元一次方程。我们可以找出一对整数(x,y),使得方程ax+by=gcd(a,b)。因为gcd(a,b)=gcd(b,a%b),所以ax+by=bx'+(a%b)y',因为a%b=a-a/b*b;所以ax+by=ay'+b(x'-(a/b)*y').
即:
x=y';
y=x'-(a/b)*y';这样运用迭代法我们就可以求出(x,y)。
扩展欧几里得算法代码:(摘自刘汝佳大神的《算法竞赛入门经典》(P179)
1 void gcd(int a,int b,int& d,int& x,int& y) 2 { 3 if(!b){d=a; x=1; y=0;} 4 else{gcd(b,a%b,d,y,x);y-=x*(a/b);} 5 }
当我们运用上述方法求出ax+by=gcd(a,b)之后,假设解为(x1,y1)我们就可以用来求ax+by=c的一组解(x0,y0),设k=c%gcd(a,b),如果k!=0,即c不是gcd(a,b)的倍数,那么此方程无整数解。
如果不等于0,那么a(x1*c/gcd(a,b))+b(y1*c/gcd(a,b))=c。所以x0=x1*c/gcd(a,b),y0=y1*c/gcd(a,b)。其余的整数解可以写成这样(x0+kb',y0-ka'),其中b'=b/gcd(a,b),a'=a/gcd(a,b)。具体推导过程请看《算法竞赛入门经典》179...记住即可。。。
对于此题我们只要枚举K,使得:
x1<=x0+kb'<=x2
y1<=y0-ka'<=y2
直接解出两个不等式的解,然后求交集即得到了K的范围,K的范围长度+1也即所有整数解的数量。
注意精度问题以及a,b,c的正负。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<stdio.h> 2 #include<math.h> 3 #include<stdlib.h> 4 typedef struct 5 { 6 long long d; 7 long long x; 8 long long y; 9 } NODE; 10 NODE gcd(long long a,long long b) 11 { 12 NODE s,p; 13 if(!b) 14 { 15 s.x=1; 16 s.y=0; 17 s.d=a; 18 return s; 19 } 20 s=gcd(b,a%b); 21 p.x=s.x; 22 s.x=s.y; 23 s.y=p.x-(a/b)*s.y; 24 return s; 25 26 } 27 long long max(long long a,long long b) 28 { 29 return a>b?a:b; 30 } 31 long long min(long long a,long long b) 32 { 33 return a<b?a:b; 34 } 35 36 int main(void) 37 { 38 long long a,b,c,x1,x2,y1,y2,ll,rr,tt; 39 scanf("%lld%lld%lld",&a,&b,&c); 40 scanf("%lld%lld",&x1,&x2); 41 scanf("%lld%lld",&y1,&y2); 42 if(a==0&&b==0) 43 { 44 if(!c)printf("%lld\n",(x2-x1+1)*(y2-y1+1)); 45 else 46 printf("0\n"); 47 } 48 else if(a==0&&b!=0) 49 { 50 if(c%b==0&&(c/b)>=y1&&(c/b)<=y2) 51 printf("%lld\n",x2-x1+1); 52 else 53 printf("0\n"); 54 } 55 else if(a!=0&&b==0) 56 { 57 if(c%a==0&&(c/a)>=x1&&(c/a)<=x2) 58 printf("%lld\n",y2-y1+1); 59 else 60 printf("\n"); 61 } 62 else 63 { 64 c=-c; 65 if(c<0) 66 { 67 a=-a; 68 b=-b; 69 c=-c; 70 } 71 if(a<0) 72 { 73 a=-a; 74 tt=x1; 75 x1=-x2; 76 x2=-tt; 77 } 78 if(b<0) 79 { 80 b=-b; 81 tt=y1; 82 y1=-y2; 83 y2=-tt; 84 } 85 NODE s=gcd(a,b); 86 if(c%s.d) 87 printf("0\n"); 88 else 89 { 90 91 s.x*=(c/s.d); 92 s.y*=(c/s.d); 93 printf("%lld %lld\n",s.x,s.y); 94 ll=max(ceil((double)(x1-s.x)*s.d/b),ceil((double)(s.y-y2)*s.d/a)); 95 rr=min(floor((double)(x2-s.x)*s.d/b),floor((double)(s.y-y1)*s.d/a)); 96 if(ll>rr) 97 printf("0\n"); 98 else 99 printf("%lld\n",rr-ll+1); 100 } 101 } 102 return 0; 103 }