• sgu 106 The equation ★★(线性方程ax+by=c限制区间的解)


    题目大意:给定a,b,c,x1,x2,y1,y2,求满足a*x+b*y+c = 0的解x满足x1<=x<=x2,y满足y1<=y<=y2.求满足条件的解的个数。 题目链接http://acm.sgu.ru/problem.php?contest=0&problem=106   让人又爱又恨的一道题……调了一下午,各种对拍,还发现网上的一份AC代码错了>.<……很看细节的一道题。我们来一步步分析~ 我们先令c = -c,转化为我们熟悉的线性方程ax + by = c.然后: ①用扩展欧几里德找到一组解(x0,y0),这个很简单。但也有需要注意的地方,比如a,b,c=0的情况需要特殊注意一下,虽然扩展欧几里德可以解出a,b,c为任何值的一组解,但是这些情况在寻求解的个数的时候还是和一般方程不太一样的。 ②我们也知道方程的通解为:           x = x0 + kb'  (1);        y = y0 - ka' (2) ;    (b' = b/gcd(a,b),   a' = a / gcd(a,b) ). 那么sgu 106就是求在范围内k能取几个: ③将x1,x2带入上面(1)方程求出k1,k2 (k1 < k2); 同理将y1, y2带入上面(2)方程求出k3, k4 (k3 < k4).则 ans = min(k2, k4) - max(k1, k3).(这个min,max,等式一时半会儿也不好解释清楚,最好还是在纸上比划比划验证一下……).  而且,注意到我们是没把x0,y0解算进去的,于是当x0,y0也在范围内时,ans+1. ④细节:边界问题:例如,如果x0 = 3, x1 = 5, x2 =7, b = 2,   那么k2 - k1 = 2 - 1 = 1,实际上[x1..x2]内是可以取到两个k的~~应该看出什么了,当xo < x1 < x2时,计算k1时要把x1-1,同理当x1 < x2 < x0时,计算k2时要把x2+1;对y0, y1, y2同理。   代码各种补丁,有点儿乱……  
    #include 
    #include 
    #include 
    using namespace std;
    long long gcd(long long a, long long b){
        if (b == 0)
            return a;
        return gcd(b, a%b);
    }
    void ext_gcd(long long a, long long b, long long &x, long long &y){
        if (b == 0){
            x = 1;
            y = 0;
            return ;
        }
        ext_gcd(b, a%b, x, y);
        long long tmp = x;
        x = y;
        y = tmp - a / b * y;
        return ;
    }
    long long num_of_equation(long long x0, long long y0, long long x1, long long y1, long long x2, long long y2, long long a, long long b){
        long long xx1 = x1, xx2 = x2, yy1 = y1, yy2 = y2;   //保留区间,最后判断x0,y0是否在区间内需要
    
        //边界处理:
        if (x0 > x2) x2 ++;
        if (x0 < x1) x1 --;
        if (y0 > y2) y2 ++;
        if (y0 < y1) y1 --;
    
        long long k1 = (x1 - x0)/b;
        long long k2 = (x2 - x0)/b;
        if (k1 > k2){
            long long tmp = k1;
            k1 = k2;
            k2 = tmp;
        }
        long long k3 = (y1 - y0)/-a;
        long long k4 = (y2 - y0)/-a;
        if (k3 > k4){
            long long tmp = k3;
            k3 = k4;
            k4 = tmp;
        }
        long long res = min(k2, k4) - max(k1, k3);
        if (x0 >= xx1 && x0 <= xx2 && y0 >= yy1 && y0 <= yy2)   res ++;
        return res < 0 ? 0 : res;
    }
    long long f(long long a, long long b, long long c, long long x1, long long x2, long long y1, long long y2){
        c *= -1;    //把c移到等式右边构成ax+by=c
    
        //特殊处理a=b=0,a=0 b!=0,a!=0 b=0的情况
        if (a == 0 && b == 0){
            if (c == 0)
                return (x2 - x1 + 1) * (y2 - y1 + 1);
            else
                return 0;
        }
        if (a == 0){
            if (c % b == 0)
                if (c/b >= y1 && c/b <= y2)
                    return (x2 - x1 + 1);
                else
                    return 0;
            else
                return 0;
        }
        if (b == 0){
            if (c % a == 0)
                if (c/a >= x1 && c/a <= x2)
                    return (y2 - y1 + 1);
                else
                    return 0;
            else
                return 0;
        }
    
        //一般情况:
        long long x0, y0, flagx = 1, flagy = 1, g = gcd(a, b);
        if (c % g != 0)
            return 0;
        a /= g;
        if (a < 0)
            a = -1*a, flagx = -1;   //把a,b都变正数(不过感觉不变也行……囧)
        b /= g;
        if (b < 0)
            b = -1*b, flagy = -1;
        c /= g;
        ext_gcd(a, b, x0, y0);
    
        x0 *= (c * flagx);      //解出了一组特殊解x0, y0
        y0 *= (c * flagy);
    
        a *= flagx;
        b *= flagy;
        return num_of_equation(x0, y0, x1, y1, x2, y2, a, b);
    }
    int main(){
        long long a, b, c, x1, x2, y1, y2;
        cin >> a >> b >> c >> x1 >> x2 >> y1 >> y2;
        cout << f(a, b, c, x1, x2, y1, y2) << endl;
        return 0;
    }
    
     
    举杯独醉,饮罢飞雪,茫然又一年岁。 ------AbandonZHANG
  • 相关阅读:
    水波图实现原理
    程序员
    从输入URL到页面加载的全过程
    前端性能优化的七大手段
    图片懒加载
    蚂蚁庄园
    关于一个无极限分类的问题
    微信JS-SDK的一点小注意
    PHP进行AES/ECB/PKCS7 padding加密的例子(mcrypt)
    PHP进行AES/ECB/PKCS7 padding加密的例子(openssl)
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/4113989.html
Copyright © 2020-2023  润新知