SGU 106 The equation(扩展欧几里得)

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=106

题意:给定方程ax+by+c=0的参数a,b,c以及x的范围[x1,x2],y的范围[y1,y2]。求由多少组解?

思路:用拓展欧几里得算法可以得出原方程的一个解。然后就可以根据这个解判断在所给的区间里有几个解。将式子化为a*x+b*y=-c。temp=Gcd(a,b,x,y),则x和y满足a*x+b*y=temp。x*=c/temp,y*=c/temp,则x和y为原方程的一个解,所有解为X=x+(b/temp)*i,Y=y+(-a/temp)*i。则用[x1,x2],[y1,y2]分别求的i的两个范围再求交即可。





i64 exGcd(i64 a,i64 b,i64 &x,i64 &y)

{

    i64 r,t;

    if(b==0)

   {

       x=1;

       y=0;

       return a;

   }

   r=exGcd(b,a%b,x,y);

   t=x;

   x=y;

   y=t-a/b*y;

   return r;



}



i64 Low(i64 i,i64 j)

{

    if(i>=0) return i/j;

    return (i+1)/j-1;

}



i64 Upper(i64 i,i64 j)

{

    if(i<=0) return i/j;

    return (i-1)/j+1;

}



void deal(i64 x,i64 y,i64 k,i64 &L,i64 &R)

{

    if(k<0)

    {

        k=-k;

        x=-x;

        y=-y;

        swap(x,y);

    }

    L=Upper(x,k);

    R=Low(y,k);

}



int main()

{

    i64 a,b,c,x1,x2,y1,y2;

    while(scanf("%I64d",&a)!=-1)

    {

        RD(b,c,x1);

        RD(x2,y1,y2);

        i64 temp;

        if(a==0&&b==0)

        {

            if(c==0) PR((x2-x1+1)*(y2-y1+1));

            else PR(0);

        }

        else if(a==0)

        {

            temp=-c/b;

            if(c%b==0&&temp>=y1&&temp<=y2) PR(x2-x1+1);

            else PR(0);

        }

        else if(b==0)

        {

            temp=-c/a;

            if(c%a==0&&temp>=x1&&temp<=x2) PR(y2-y1+1);

            else PR(0);

        }

        else

        {

            i64 x,y;

            temp=exGcd(a,b,x,y);

            if(c%temp)

            {

                PR(0);

                continue;

            }

            c=-c;

            i64 s1,s2,t1,t2;

            x*=c/temp;

            y*=c/temp;

            deal(x1-x,x2-x,b/temp,s1,t1);

            deal(y1-y,y2-y,-a/temp,s2,t2);

            x=max(s1,s2);

            y=min(t1,t2);

            i64 ans=max(0,y-x+1);

            PR(ans);

        }

    }

    return 0;

}

  

你可能感兴趣的:(IO)