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;
}

欢迎关注我的公众号:智子笔记

posted @ 2021-02-05 16:27  David24  阅读(119)  评论(0编辑  收藏  举报