『题解』Luogu P8344 「Wdoi-6」走在夜晚的莲台野
题目大意
有 \(x\) 个金色木板,\(y\) 个银色木板,还有一个可以放 \(z\) 个木板的空容器。
每向容器中放入一个金色木板后,会丢掉容器内的所有银色木板(放金色木板前,容器里至少要能放下一个木板)。
问是否存在一种方式,使得所有木板都被放进过容器中。
多组数据。
思路
看一眼数据范围,\(1 \le T \le 1000,1 \le x,z \le 10^9,1 \le y \le 5 \times 10^{17}\),显然每次询问需要 \(\mathcal O(1)\) 时间。
先来看一个例子:\(x=2,y=7,z=4\)。
那么一种操作过程就是:
- 放 \(3\) 个银色木板。此时剩余 \(1\) 个木板的空间。
- 放 \(1\) 个金色木板,扔掉前面 \(3\) 个银色木板。此时剩余 \(3\) 个木板的空间。
- 放 \(2\) 个银色木板。此时剩余 \(1\) 个木板的空间。还剩 \(2\) 个银色木板未进入过容器。
- 放 \(1\) 个金色木板,扔掉前面放的两个银色木板,但第一个金色木板不扔。此时剩余 \(2\) 个木板的空间。
- 放 \(2\) 个银色木板,刚好填满容器,且所有木板进入过容器,操作结束。
通过观察可以发现,在金色木板用完之前,每次可以放入并在下一次放入金色木板时扔掉的银色木板数分别为:\(z-1,z-2,\dots,z-x\)。
那么,我们就可以利用高斯求和公式 \(\textsf{等差数列之和}=\dfrac{(\textsf{首项}+\textsf{末项})\times\textsf{项数}}{2}\) 求出可以利用金色木板抵消掉的银色木板总数,即 \(\dfrac{[(z-x)+(z-1)] \times x}{2}\)。
在这些银色木板都被抵消后,\(x\) 个金色木板都被放入了容器中,因此容器还能装的木板数量就为 \(z-x\)。因为金色木板都放完了,剩下 \(z-x\) 个空间就可以用来放银色木板了。
我们就可以很轻松地求出最大可以放的银色木板数量了:\(\dfrac{[(z-x)+(z-1)] \times x}{2}+z-x\)。
若这个值 \(\ge y\),那么操作就是可以完成的。
还要注意一种不能完成操作的情况:\(x>z\),若是金色木板数量比容量还大,那是无论如何也装不下去的。除非你把容器扒得超级大。
那么能完成操作的时候当 \(x \le z\) 和 \(\dfrac{[(z-x)+(z-1)] \times x}{2}+z-x \ge y\) 同时成立的时候。
注意开 long long。
代码
#include <iostream>
using namespace std;
template<typename T=long long>
inline T read(){
T X=0; bool flag=1; char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') flag=0; ch=getchar();}
while(ch>='0' && ch<='9') X=(X<<1)+(X<<3)+ch-'0',ch=getchar();
if(flag) return X;
return ~(X-1);
}
typedef long long ll;
ll t,x,y,z;
int main(){
t=read();
while(t--){
x=read(),y=read(),z=read();
if(x<=z && ((z-x)+(z-1))*x/2+z-x>=y) puts("Renko");
else puts("Merry");
}
return 0;
}

浙公网安备 33010602011771号