Codeforces Round #689 (Div. 2, based on Zed Code Competition) E. Water Level (贪心好题)
阅读原文时间:2023年07月09日阅读:3

  • 题意:你在一家公司工作\(t\)天,负责给饮水机灌水,饮水机最初有\(k\)升水,水的范围必须要在\([l,r]\)内,同事每天白天都会喝\(x\)升水,你在每天大清早可以给饮水机灌\(y\)升水,问你在公司工作的这几天内,饮水机会不会发生故障.

  • 题解:假如\(x>=y\),那么,我们贪心的思路一定是每天让水减的尽可能少,所以每天都要加水,这里要注意第一天的情况,如果第一天加水后大于\(r\)话,那么第一天大清早是不能加水的,这里我们要特判一下,接下来用if判断就行了.

    假如\(x < y\)的话,那么我们可以让同事一直喝,喝到极限为止,然后我们加一次水,再让同事一直喝,如此往复,不难发现,这样会出现循环节,我们每次记录饮水机的水量,如果相同水量出现两次,那么一定是可以无限循环的(因为同事喝到极限的水量和我每次加水的量是固定的).我们用map标记一下就好了.

  • 代码:

    #include
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    #define rep(a,b,c) for(int a=b;a<=c;++a) #define per(a,b,c) for(int a=b;a>=c;--a)
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair PII;
    typedef pair PLL;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}

    ll k,l,r,t,x,y;
    map vis;

    bool check(ll x){
    if(x>=l && x<=r) return true;
    return false;
    }

    int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    cin>>k>>l>>r>>t>>x>>y;
    
    if(x>=y){
        if(k+y>r){
            k-=x;
            t--;
        }
        if(!check(k)){
            cout<<"NO\n";
            return 0;
        }
        ll cnt=x-y;
        if(cnt==0){
            cout<<"YES\n";
            return 0;
        }
        if((k-l)/cnt>=t) cout<<"YES\n";
        else cout<<"NO\n";
    }
    else{
        ll cnt=(k-l)/x;
        if(cnt>=t){
            cout<<"YES\n";
            return 0;
        }
        k-=cnt*x;
        t-=cnt;
    while(t&gt;0 &amp;&amp; !vis[k]){
        vis[k]=1;
        k+=y;
        if(!check(k)){
            cout&lt;&lt;"NO\n";
            return 0;
        }
        cnt=(k-l)/x;
        t-=cnt;
        k-=cnt*x;
    }
    cout&lt;&lt;"YES\n";
    } return 0;

    }