Codeforces Round #689 (Div. 2, based on Zed Code Competition) E. Water Level (贪心好题)

  • 题意:你在一家公司工作(t)天,负责给饮水机灌水,饮水机最初有(k)升水,水的范围必须要在([l,r])内,同事每天白天都会喝(x)升水,你在每天大清早可以给饮水机灌(y)升水,问你在公司工作的这几天内,饮水机会不会发生故障.
  • 题解:假如(x>=y),那么,我们贪心的思路一定是每天让水减的尽可能少,所以每天都要加水,这里要注意第一天的情况,如果第一天加水后大于(r)话,那么第一天大清早是不能加水的,这里我们要特判一下,接下来用if判断就行了.
    假如(x < y)的话,那么我们可以让同事一直喝,喝到极限为止,然后我们加一次水,再让同事一直喝,如此往复,不难发现,这样会出现循环节,我们每次记录饮水机的水量,如果相同水量出现两次,那么一定是可以无限循环的(因为同事喝到极限的水量和我每次加水的量是固定的).我们用map标记一下就好了.
  • 代码:
#include <bits/stdc++.h>
#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<int,int> PII;
typedef pair<ll,ll> 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<ll,int> 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
";
			return 0;
		}
		ll cnt=x-y;
		if(cnt==0){
			cout<<"YES
";
			return 0;
		}
		if((k-l)/cnt>=t) cout<<"YES
";
		else cout<<"NO
";
	}
	else{
		ll cnt=(k-l)/x;
		if(cnt>=t){
			cout<<"YES
";
			return 0;
		}
		k-=cnt*x;
		t-=cnt;

		while(t>0 && !vis[k]){
			vis[k]=1;
			k+=y;
			if(!check(k)){
				cout<<"NO
";
				return 0;
			}
			cnt=(k-l)/x;
			t-=cnt;
			k-=cnt*x;
		}
		cout<<"YES
";
	}

    return 0;
}
原文地址:https://www.cnblogs.com/lr599909928/p/14170069.html