[CF1461E] Water Level
Description
饮水机中本来有 (k) 升水,John希望在 (t) 天内饮水机的水量在 ([l,r]) 之间,John知道每一天饮水机会被用掉正好 (x) 升水,而John可以在一天的开始选择加正好 (y) 升水(一天只能加一次)或不加水.给出 (k,l,r,t,x,y).求能否在 (t) 天内把水量控制在 ([l,r]).能输出 Yes
,否则输出 No
. (1leq lleq kleq rleq 10^{18},1leq tleq10^{18},1leq xleq10^6,1leq yleq10^{18}.)
Solution
分 (y=x,y<x,y>x) 三种情况考虑
这里主要说 (y>x)
我们尽可能让它减到不能再减,然后加一次
循环的结束条件为 t=0 或者发现水量序列出现了循环节
这是大体的思路,诸多的细节难以详述,见代码
#include <bits/stdc++.h>
using namespace std;
#define int __int128
int t, l, r, k, x, y;
signed main()
{
ios::sync_with_stdio(false);
long long t1, t2, t3, t4, t5, t6;
cin >> t1 >> t2 >> t3 >> t4 >> t5 >> t6;
k = t1;
l = t2;
r = t3;
t = t4;
x = t5;
y = t6;
if (x == y)
{
if (k + y <= r || k - x >= l)
cout << "Yes" << endl;
else
cout << "No" << endl;
}
else if (y < x)
{
if (k + y <= r)
k += y;
int t0 = (k - l - y) / (x - y);
cout << (t0 >= t ? "Yes" : "No") << endl;
}
else
{
if (k + y <= r)
k += y;
set<int> s;
s.insert(k);
while (t > 0)
{
int d = min((k - l) / x, t);
k -= d * x;
t -= d;
if (d == 0)
{
cout << "No" << endl;
return 0;
}
if (s.find(k) != s.end())
{
cout << "Yes" << endl;
return 0;
}
s.insert(k);
if (t == 0)
break;
k += y;
if (k > r)
{
cout << "No" << endl;
return 0;
}
if (s.find(k) != s.end())
{
cout << "Yes" << endl;
return 0;
}
s.insert(k);
if (d == 0)
{
cout << "No" << endl;
return 0;
}
}
cout << "Yes" << endl;
}
}