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

没想起来怎么做这里写图片描述
参考:https://www.cnblogs.com/zjbztianya/archive/2013/03/12/2956835.html

思路还是很简单的,ax+by=c, gcd(a,b)=d,则x = x0+(b/d) * t,y = y0 - (a/d) * t,每个t确定一对解,现在已经知道x1<=x<=x2,y1<=y<=y2,代换一下,求出来t的范围即可,有多少个t的整数解,结果就是几。

#include 
using namespace std;
long long extend_gcd(long long a,long long b,long long &x,long long &y)
{
    if(a==0&&b==0) return -1;//无最大公约数
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    long long d=extend_gcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}

int main()
{
    long long a,b,c,x1,y1,x2,y2,x,y,tx,ty,d,l,r;
    scanf("%lld %lld %lld %lld %lld %lld %lld",&a,&b,&c,&x1,&x2,&y1,&y2);
    if(a == 0 && b == 0)
    {
        if(c == 0)  printf("%lld\n",(x2-x1+1)*(y2-y1+1));
        else printf("0\n");
    }
    else if(a == 0)
    {
        if(c%b == 0 && (c/b) >= y1 && (c/b) <= y2) printf("%lld\n",x2-x1+1);
        else printf("0\n");
    }
    else if(b == 0)
    {
        if(c%a == 0 && (c/a) >= x1 && (c/a) <= x2) printf("%lld\n",y2-y1+1);
        else printf("0\n");
    }
    else
    {
        c = -c;
        if(c < 0)
        {
            c = -c;
            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);
        }
        d = extend_gcd(a,b,x,y);
        if(c%d) printf("0\n");
        else
        {
            tx = x*(c/d);
            ty = y*(c/d);
            l = max(ceil((double)(x1-tx)*d/b), ceil((double)(ty-y2)*d/a));
            r = min(floor((double)(x2-tx)*d/b), floor((double)(ty-y1)*d/a));
            if(l > r) printf("0\n");
            else printf("%lld\n",r-l+1);
        }
    }
    return 0;
}

你可能感兴趣的:(欧几里德/扩展欧几里德)