【Codeforces 1461E】Water Level

题目链接

链接

翻译

让你维持水位始终在 [l,r] 这个范围

且,你每天开始的时候可以加(所以也可以不加) \(y\) 升水,然后结束的时候会少掉 \(x\) 升水(固定)。

一开始水位是 \(k\),问你这样(水位始终在 [l,r] 这个区间) 能否持续 \(t\) 天。

题解

如果 \(y<x\),那么显然水位只会一直下降。则一开始如果水位大于 \(r-y\) 那么就每次只减少 \(x\)。到了 \(r-y\) 以后,每次能增加 \(y\) 了。

则每次减少 \(x-y\)。模拟一下就好,注意如果一直减 \(x\) 出现了要减到 \(l\) 以下才能到 \(r-y\) 以下的话,那么最后向上取整的天数要删掉。因为不能到那一天了。。

嗯。。现在跟你说这些你又怎么会懂呢,自己写代码试试(WA一下)就知道了hhh

如果 \(y>=x\), 那么一个比较机智的方法就是,一直减 \(x\) 减到 \(k-x*((k-l)/x)\) 即左边界的边缘。然后再加一次 \(y\),然后再减 \(x\) 减到

边缘。这样是不是没有止境了呢? 不是的,因为你每次减到边缘之后,水位其实就是 \(l+(k-l+times*y)\%x\), 这里的 \(times\) 就是你每次加一次 \(y\) 总共加的

次数。这显然是有循环节的,而 \(x\) 的最大值才 \(10^6\),那么就是一个 \(\mathcal{O(N)}\) 的算法啦。

出现了循环节就直接输出 \(Yes\) 就好。

代码

#include <bits/stdc++.h>
#define LL long long
using namespace std;

const int X = 1e6;

vector<int> ans;
LL k,l,r,t,x,y;
bool bo[X+10];

void _judge(LL days){
    if (days >= t){
        cout << "Yes" << endl;
    }else{
        cout << "No" << endl;
    }
}

int main(){
    // freopen("C://1.cppSourceProgram//rush.txt","r",stdin);
    ios::sync_with_stdio(0),cin.tie(0);
    //1 input data
    cin >> k >> l >> r >> t >> x >> y;
    //2 y < x continue subtraction
    if (y < x){
        LL t0 = 0;
        //3 sub x first until that k+y <= r ie. k<=r-y
        //
        if (k>r-y){
            //4 r-y < l no add just go die
            if (r - y < l){
                t0 = (k-l)/x;
                _judge(t0);
                return 0;
            }else{
                //5 r - y >= l, cal first t0 days to let k <=r-y
                t0 = (k-(r-y)-1)/x+1;
                k -= t0*x;
            }
        }
        //k <= r-y
        //6 k < l ->output t0
        if (k < l){
            //最后一天不能加上
            t0--;
            _judge(t0);
            return 0;
        }
        //7 l <= k <= r-y
        //add y  sub  x  and  x > y
        LL t1 = (k-l)/(x-y);
        _judge(t0+t1);
    }else{
        // y >= x
        //8 增加的比减少的多
        //减到不能减为止,然后开始加。再减到不能减为止,再加一次。直到出现循环,或者超出界限。
        // 9 先减到不能减为止
        LL t0 = 0;
        t0 += (k-l)/x;
        k -= t0*x;
        // 10 令 delta = k-l
        LL delta = k - l;
        // 开始让这个数加 y 然后对 x 取模(对应再减到不能减)。直到出现重复为止。
        bo[delta] = true;
        delta = delta+y;
        while (delta <= r-l){
            t0 += delta/x;
            if (t0>=t){
                break;
            }
            delta = delta%x;
            if (bo[delta]){
                t0 = t;
                break;
            }
            bo[delta] = true;
            delta = delta + y;
        }
        _judge(t0);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值