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的正负。

 

View Code
  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 }

 

 

 

 

 

 

posted on 2013-03-12 23:55  仗剑奔走天涯  阅读(355)  评论(0编辑  收藏  举报

导航