• SGU 106 在区间范围内的线性方程解个数


    题意:求解方程ax+by+c=0,在区间x1->x2和y1->y2的解的个数。
    看似简单,真心a的不容易啊!
    开始跪于第8组数据,原因是没用long long !后来改了,跪于12组,超时,于是,换方法,求出x的解,对应到y
    ,然后算在y1,y2的解有几个(不要用枚举法,算有几个就行)。竟然又跪于第4组数据!!哎,弱爆了。
    才发现,x对应过去的y,x递增,y未必也递增,也未必递减啊!!
    做线方程总结:
    先判断有无解,再约分后得 ax+by=c,用扩展欧几里得求得ax+by=1的一解,x=x*c,y=y*c,便是原方程一组解了,
    每俩个相邻解x,相差|b|,同理,y差|a|,然后就是看题目要求了,见招拆招了,如想要到去某点附近的解,

    可以 x=x-(x1-x)/abs(b)*abs(b);(可能左右)。


    #include<iostream>
    #include<cmath>
    using namespace std;
    long long gcd(long long  a,long long  b)
    {
        return b==0?a:gcd(b,a%b);
    }
    void exgcd(long long a,long long  b,long long &x,long long  &y)
    {
        if(b==0){x=1;y=0;}
        else
        {
            exgcd(b,a%b,y,x);y=y-x*(a/b);
        }
    }
    inline long long getabs(long long  a)
    {
      return a<0?-a:a;
    }
    int main()
    {
        long long a,b,c,x1,x2,y1,y2;
        cin>>a>>b>>c>>x1>>x2>>y1>>y2;
        long long x,y;
        c=-c;                                         //移项
        if(x1>x2||y1>y2){cout<<0<<endl;return 0;}    //排除无解的情况
        if(a==0&&b==0)                               //特殊情况讨论
        { 
            long long ans=0;
            if(c==0)                                 
            {
                 ans=(x2-x1+1)*(y2-y1+1);          //此处任意组合都可以
            }
              cout<<ans<<endl;
              return 0;
        }
        if(a==0)
        {
            if(c%b!=0){cout<<0<<endl;return 0;}
            else
            {
                y=c/b;
                if(y>=y1&&y<=y2)
                    cout<<x2-x1+1<<endl;
                else cout<<0<<endl;
                return 0;
            }
        }
        if(b==0)
        {
            if(c%a!=0){cout<<0<<endl;return 0;}
            else
            {
                x=c/a;
                if(x>=x1&&x<=x2)cout<<y2-y1+1<<endl;
                else cout<<0<<endl;
                return 0;
            }
        }
        long long g=getabs(gcd(a,b));
        if(c%g!=0){cout<<0<<endl;return 0;}
        a=a/g;b=b/g;c=c/g;                       //约去最大公约数
    
        exgcd(a,b,x,y);                         //求得一组解
        x=x*c;
        y=y*c;                                 //原方程一组解
        x=x-(x-x1)/getabs(b)*getabs(b);        //得与x1最近的一解x(x>=x1)
        while(x<x1)x+=getabs(b);
        if(x>x2){cout<<0<<endl;return 0;}
        long long xx=x+(x2-x)/getabs(b)*getabs(b);  //解x->xx(x>=x1,xx<=x2)
        y=(c-a*x)/b;                           //对应yy,y,注意,此处yy,y大小不知道!!
        long long yy=(c-a*xx)/b;
        long long ans=0;
       /*   while(x<=xx)                      //若用枚举解,超时
          { 
               if(y>=y1&&y<=y2)ans++;
               x+=getabs(b);
              y=(c-a*x)/b;
          }*/
         if(yy>y){long long temp=y;y=yy;yy=temp;}   //大小决定一下
           if(yy<y1)                               //取在区间y1->y2之间的解。(y,yy为边界解)
           {
               yy=yy+(y1-yy)/getabs(a)*getabs(a);
               while(yy<y1)yy+=getabs(a);
           }
           if(y2<y)
           {
               y=y-(y-y2)/getabs(a)*getabs(a);
               while(y>y2)y-=getabs(a);
           }
         if(y>=yy)
             ans=(y-yy)/getabs(a)+1;
        cout<<ans<<endl;
    }
    



  • 相关阅读:
    Github 简明教程--GitHub这么火,测试员你不学学吗?
    IT行业,尤其是软件测试,怎么才能月薪突破2万?
    linux 下cmake 编译 ,调用,调试 poco 1.6.0 小记
    ffmpeg(2.6) rockplayer android 下编译 小记.
    完成端口
    C++四种强制转换
    方法区(Method Area)基础知识
    逃逸分析
    堆空间参数设置小结
    堆中的线程私有缓存区域TLAB(Thread Local Allocation Buffer)
  • 原文地址:https://www.cnblogs.com/yezekun/p/3925796.html
Copyright © 2020-2023  润新知