美文网首页
2017.07.15【NOIP提高组】模拟赛B组 不等式(sol

2017.07.15【NOIP提高组】模拟赛B组 不等式(sol

作者: mijoe10 | 来源:发表于2017-07-15 19:30 被阅读0次

    原题:

    http://172.16.0.132/senior/#contest/show/2061/2

    题目描述:

    小z热衷于数学。
    今天数学课的内容是解不等式:L<=Sx<=R。小z心想这也太简单了,不禁陷入了深深的思考:假如已知L、R、S、M,满足L<=(Sx)mod M<=R的最小正整数x该怎么求呢?

    输入:

    第一行包含一个整数T,表示数据组数,接下来是T行,每行为四个正整数M、S、L、R。

    输出:

    对于每组数据,输出满足要求的x值,若不存在,输出-1。

    样例输入:

    1
    5 4 2 3

    样例输出:

    2

    数据范围限制:

    30%的数据中保证有解并且答案小于等于10^6;
    另外20%的数据中保证L=R;
    100%的数据中T<=100,M、S、L、R<=10^9。

    分析:

    对于的做法,首先我们排除特殊情况,不妨设,0<=l<=r,0<=s<=m。
    显然若存在一个的倍数满足l<=sx<=r,那么此时的答案就是x。
    若不存在,我们不妨将约束式改写成代数式l<=s
    x-my<=r。进一步改写成以为y主元,即-r<=my-sx<=-l,再把它还原为取模的形式:(-r mod s)<=my mod s<=(-l mod s)。若能求出最小的满足上式的y值,则可以求出唯一满足上式的x值(因为区间中没有s的倍数)。
    所以我们只需要将读入的四个数标准化,判断是否存在简单解以及判断无解,假如需要的话递归调用函数,直至问题解决。

    实现:

    #include<cstdio>
    
    long long t,m,s,l,r;
    long long dg(long long m,long long s,long long l,long long r)
    {
        if(l==0) return 0;
        if(l>=m || l>r || s%m==0) return -1;
        s%=m;
        long long x=(l-1)/s+1;
        if(x*s<=r) return x;
        long long y=dg(s,m,(-r%s+s)%s,(-l%s+s)%s);
        if(y==-1) return y;
        x=(r+m*y)/s;
        if(s*x-m*y>=l) return (x%m+m)%m;
        return -1;
    }
    int main()
    {
        freopen("solve.in","r",stdin);freopen("solve.out","w",stdout);
        scanf("%lld",&t);
        while(t--)
        {
            scanf("%lld%lld%lld%lld",&m,&s,&l,&r);
            if(r>=m) r=m-1;
            printf("%lld\n",dg(m,s,l,r));
        }
    }
    

    相关文章

      网友评论

          本文标题:2017.07.15【NOIP提高组】模拟赛B组 不等式(sol

          本文链接:https://www.haomeiwen.com/subject/kyjzhxtx.html