CF965C 贪婪的Arkady
1 CF965C 贪婪的Arkady
2 题目描述
\(k\) 个人分 \(n\) 个糖果,每个糖果要么分给某人要么扔掉,不能分割。人的编号从 \(1\) 到 \(k\),\(Arkady\) 排第一位。要分糖果,\(Arkady\) 将选择一个整数 \(𝑥\) 然后将第一份 \(𝑥\) 个糖果给自己,下一份 \(𝑥\) 个糖果给第二个人,再下一份 \(x\) 个糖果给第三个人,依次循环。最后剩下的(不能被 \(𝑥\) 整除的余数)将被扔掉。
\(Arkady\) 不能选择比 \(𝑀\) 大的 \(𝑥\),因为这样会被认为是贪婪的。此外,他不能选择太小的 \(𝑥\),这样有些人会收到超过 \(𝐷\) 次的糖果,这种分法太慢。
请通过选择一些有效的 \(𝑥\),找到 \(Arkady\) 可以接收的糖果的最大数量。
3 题解
这道题的数据范围还是很大,但是我们意外地发现,\(D\) 的范围很小,我们便可以考虑以 \(D\) 为根据的算法,即枚举了进行的轮数。
我们发现,进行了几轮的糖果分配比较不好算,我们可以稍微转换一下,把每一轮看作多出了 \(k\) 个人。假设进行了 \(x\) 轮,我们就可以看作分给了 当前轮分到的人数 \(+(x-1)*k\) 人。我们容易想到,要让第一个人的利益最大化,我们最好当前轮在分完第一个人后就无法再分了,否则如果能分给更多的人,第一个人的利益不一定最大。那么我们一共要分给的人就是 \((x-1)*k+1\) 个,每个人能得到的糖数就是 \(\lfloor \frac{n}{(x-1)*k + 1} \rfloor\),第一个人能得到的糖果数就是 \(x * \lfloor \frac{n}{(x-1)*k+1} \rfloor\)。注意:我们算出的这个值可能会大于 \(M\),所以要与 \(M\) 取 \(min\)。
我们如此写完后,发现我们仍然错误,原因是,随着 \(x\) 的不断增大,\((x-1)*k\) 的值可能会大于 \(long \space long\) 的上限。难道我们真的要打高精度吗?其实不然。我们发现:当 \((x-1)*k+1\) 超过 \(n\) 时,虽然可能会超出上限,但此时每个人能分配到的糖果数小于 \(1\) 个,此时明显不符合题意,我们跳出即可。这样答案就不会出现爆出 \(long \space long\) 的情况。
4 代码(空格警告):
#include <iostream>
using namespace std;
long long n, k, M, D, x, maxn;
int main()
{
cin >> n >> k >> M >> D;
for (int i = 1; i <= D; i++)
{
x = min(M, n / ((i - 1) * k + 1));
if (x == 0) break;
maxn = max(maxn, x * i);
}
cout << maxn;
return 0;
}