1. 程式人生 > 其它 >E. Water Level(codeforces #689 div2 )

E. Water Level(codeforces #689 div2 )

技術標籤:思維cf數論

E. Water Level

題意:初始水量為k,每天你可以使水量加y,然後每天必定消耗x的水,水量要始終在範圍[L,R]中,問你能不能堅持t天

資料範圍:

題解:

當x>=y時,這種情況好處理,就是(1)加y超過r時,每天減少x,(2)加y合法時,此後每天減少x-y。模擬即可

當x<y時,不妨不加水,讓他每天只消耗水,知道水量為大於等於L的最小值(記為rst),然後再加水,重複這個過程,還有時間當時不能加水就是No

根據數論知識,能夠知道rst最後會迴圈出現,所以用map記一下所有的rst,出現以前出現過的就可以跳出了

所有的rst都小於x,x的範圍較小,時間複雜度O(xlogx)

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

#define ll long long
ll x,y,t,l,r,k,tmp;
map<ll,int>mp;

ll cal(ll a,ll b){//多少個b使得減去a使得其值小於等於0 
	return a/b+(a%b!=0);
}

int main()
{
	scanf("%lld%lld%lld%lld%lld%lld",&k,&l,&r,&t,&x,&y);
	//x>=y
	if(x>=y){
		ll ls=r-y;
		if(ls<l){
			printf("No\n"); return 0;	
		}
		ll ti=0;
		if(k>ls){
			tmp=cal(k-ls,x);
			ti=tmp;
			k-=tmp*x;
		}
		if(k>=l){
			if(x>y){
				tmp=cal(k-l+1,x-y);//這裡因為寫成cal(k-l-1,x-y),wa了一發 
				ti+=tmp;
			}
			else{
				printf("Yes\n"); return 0;
			}
		}
		if(ti>t)printf("Yes\n");
		else printf("No\n");
		return 0;
	}
	
	//x<y
	t-=(k-l)/x;
	ll rst=(k-l)%x;
	mp[rst]=1;
	int fl=1;
	while(t>0){//long long,此處判斷t是否為0,所以不能直接while(t) ,因此wa了一發 
		if(l+y+rst>r){
			fl=0; break;
		}
		t-=(y+rst)/x;
		rst=(y+rst)%x;
		if(mp[rst])break;
		mp[rst]=1;
	}
	if(fl)printf("Yes\n");
	else printf("No\n");
	return 0;
}