【牛客周赛 107】E 题【小苯的刷怪笼】题解

题目链接

题目大意

给定三个正整数 n , a , k n, a, k n,a,k,其中:

  • n n n 为怪物的数量, n n n 个怪物站成一排,从左到右编号 1 1 1 到 n n n;
  • a a a 为 n n n 个怪物的血量和,且每个怪物的血量都是正数;
  • k k k 为小苯的操作次数。

每次操作,小红会选择一个或相邻两个怪物,使得它(们)的血量(各自) − 1 -1 −1。当怪物的血量 ≤ 0 \leq 0 ≤0 时,怪物被消灭(相邻关系不会改变)。

小红一定会选择最优策略,使用尽可能少的攻击次数消灭这些怪物。

在这种情况下,小苯希望小红能使用恰好 k k k 次攻击消灭所有的怪物。

请你帮小苯找出一个可能的血量分配方案,如果不行输出 − 1 -1 −1。

数据范围

  • 1 ≤ n ≤ 2 ⋅ 1 0 5 , 1 \leq n \leq 2 \cdot 10^5, 1≤n≤2⋅105,
  • n ≤ a ≤ 1 0 9 , n \leq a \leq 10^9, n≤a≤109,
  • 1 ≤ k ≤ 1 0 9 . 1 \leq k \leq 10^9. 1≤k≤109.

Solution

首先, n = 1 n = 1 n=1 时,只能将 a a a 分配给一个怪物,所以只要看是否有 a = k a = k a=k。

下面考虑 n > 1 n > 1 n>1 的情况。

由于需要恰好 k k k 次操作,所以我们需要找到操作次数的上下界。

先找下界 L L L。

  • 要想操作次数接近下界 L L L,就要尽可能让小红选择相邻两个怪物一起扣血;
  • 首先为每个怪物分配 1 1 1 生命值,这样还剩下 a − n a - n a−n 的血量和;
  • 然后我们再分配 ⌊ a − n 2 ⌋ \left\lfloor \dfrac{a - n}{2} \right\rfloor ⌊2a−n⌋ 给怪物 1 1 1,分配 ⌈ a − n 2 ⌉ \left\lceil \dfrac{a - n}{2} \right\rceil ⌈2a−n⌉ 给怪物 2 2 2。
  • 当 n n n 是偶数,
    • 小红先通过 n 2 \dfrac{n}{2} 2n 次操作消除下面分配的 1 1 1 生命值,然后再通过 ⌈ a − n 2 ⌉ \left\lceil \dfrac{a - n}{2} \right\rceil ⌈2a−n⌉ 次操作消灭怪物 1 1 1 和 2 2 2;
    • 操作次数为 n 2 + ⌈ a − n 2 ⌉ = ⌈ a 2 ⌉ \dfrac{n}{2} + \left\lceil \dfrac{a - n}{2} \right\rceil = \left\lceil \dfrac{a}{2} \right\rceil 2n+⌈2a−n⌉=⌈2a⌉;
  • 当 n n n 是奇数,
    • 小红先通过 ⌈ n 2 ⌉ \left\lceil \dfrac{n}{2} \right\rceil ⌈2n⌉ 次操作消除下面分配的 1 1 1 生命值,这时会影响到怪物 2 2 2 的血量会提前 − 1 -1 −1,变为 ⌈ a − n 2 ⌉ − 1 ≤ ⌊ a − n 2 ⌋ \left\lceil \dfrac{a - n}{2} \right\rceil - 1 \leq \left\lfloor \dfrac{a - n}{2} \right\rfloor ⌈2a−n⌉−1≤⌊2a−n⌋,所以再通过 ⌊ a − n 2 ⌋ \left\lfloor \dfrac{a - n}{2} \right\rfloor ⌊2a−n⌋ 次操作就能消灭怪物 1 1 1 和 2 2 2;
    • 操作次数为 ⌈ n 2 ⌉ + ⌊ a − n 2 ⌋ = ⌊ n + 1 2 ⌋ + ⌊ a − n 2 ⌋ = ⌊ a + 1 2 ⌋ = ⌈ a 2 ⌉ \left\lceil \dfrac{n}{2} \right\rceil + \left\lfloor \dfrac{a - n}{2} \right\rfloor = \left\lfloor \dfrac{n + 1}{2} \right\rfloor + \left\lfloor \dfrac{a - n}{2} \right\rfloor = \left\lfloor \dfrac{a + 1}{2} \right\rfloor = \left\lceil \dfrac{a}{2} \right\rceil ⌈2n⌉+⌊2a−n⌋=⌊2n+1⌋+⌊2a−n⌋=⌊2a+1⌋=⌈2a⌉;
  • 这样就说明操作次数下界 L = ⌈ a 2 ⌉ L = \left\lceil \dfrac{a}{2} \right\rceil L=⌈2a⌉。

再找上界 R R R。

  • 要想操作次数接近上界 R R R,就要尽可能让小红只选择一个怪物扣血;
  • 首先为每个怪物分配 1 1 1 生命值,这样还剩下 a − n a - n a−n 的血量和;
  • 然后我们直接给怪物 1 1 1 分配 a − n a - n a−n 的血量。
  • 当 n n n 是偶数,
    • 小红先通过 n 2 \dfrac{n}{2} 2n 次操作消除下面分配的 1 1 1 生命值,然后再通过 a − n a - n a−n 次操作消灭怪物 1 1 1;
    • 操作次数为 n 2 + ( a − n ) = a − n 2 = a − ⌊ n 2 ⌋ \dfrac{n}{2} + (a - n) = a - \dfrac{n}{2} = a - \left\lfloor \dfrac{n}{2} \right\rfloor 2n+(a−n)=a−2n=a−⌊2n⌋;
  • 当 n n n 是奇数,
    • 小红先通过 ⌈ n 2 ⌉ \left\lceil \dfrac{n}{2} \right\rceil ⌈2n⌉ 次操作消除下面分配的 1 1 1 生命值,这时怪物 1 1 1 不受影响,还剩 a − n a - n a−n 的血量值,我们再通过 a − n a - n a−n 次操作消灭怪物 1 1 1;
    • 操作次数为 ⌈ n 2 ⌉ + ( a − n ) = a − ⌊ n 2 ⌋ \left\lceil \dfrac{n}{2} \right\rceil + (a - n) = a - \left\lfloor \dfrac{n}{2} \right\rfloor ⌈2n⌉+(a−n)=a−⌊2n⌋;
  • 这样就说明操作次数上界 R = a − ⌊ n 2 ⌋ R = a - \left\lfloor \dfrac{n}{2} \right\rfloor R=a−⌊2n⌋。

所以只有当 ⌈ a 2 ⌉ ≤ k ≤ a − ⌊ n 2 ⌋ \left\lceil \dfrac{a}{2} \right\rceil \leq k \leq a - \left\lfloor \dfrac{n}{2} \right\rfloor ⌈2a⌉≤k≤a−⌊2n⌋ 时,才有可能构造一个合法分配。


考虑从上界 R = a − ⌊ n 2 ⌋ R = a - \left\lfloor \dfrac{n}{2} \right\rfloor R=a−⌊2n⌋ 开始调整。

此时怪物 1 1 1 除了底部的 1 1 1 血量值,还有额外分配的 a − n a - n a−n 血量值,我们将其拿出 s s s 来分配给怪物 2 2 2,这样怪物 1 1 1 的额外血量为 a − n − s a - n - s a−n−s,怪物 2 2 2 的额外血量为 s s s。

接着考虑这种分配下的操作次数。

  • 当 n n n 是偶数,需要满足 a − n − s ≥ s a - n - s \geq s a−n−s≥s,即 s ≤ ⌊ a − n 2 ⌋ s \leq \left\lfloor \dfrac{a - n}{2} \right\rfloor s≤⌊2a−n⌋;
    • 小红先通过 n 2 \dfrac{n}{2} 2n 次操作消除下面分配的 1 1 1 生命值,然后再通过 a − n − s a - n - s a−n−s 次操作消灭怪物 1 1 1 和 2 2 2;
    • 操作次数为 n 2 + ( a − n − s ) = a − n 2 − s = a − ⌊ n 2 ⌋ − s \dfrac{n}{2} + (a - n - s) = a - \dfrac{n}{2} - s = a - \left\lfloor \dfrac{n}{2} \right\rfloor- s 2n+(a−n−s)=a−2n−s=a−⌊2n⌋−s;
  • 当 n n n 是奇数,需要满足 a − n − s ≥ s − 1 a - n - s \geq s - 1 a−n−s≥s−1,即 s ≤ ⌊ a − n + 1 2 ⌋ = ⌈ a − n 2 ⌉ s \leq \left\lfloor \dfrac{a - n + 1}{2} \right\rfloor = \left\lceil\dfrac{a - n}{2} \right\rceil s≤⌊2a−n+1⌋=⌈2a−n⌉;
    • 小红先通过 ⌈ n 2 ⌉ \left\lceil \dfrac{n}{2} \right\rceil ⌈2n⌉ 次操作消除下面分配的 1 1 1 生命值,这时怪物 2 2 2 受到影响,还剩 s − 1 s - 1 s−1 的血量值,我们再通过 a − n − s a - n - s a−n−s 次操作消灭怪物 1 1 1 和 2 2 2;
    • 操作次数为 ⌈ n 2 ⌉ + ( a − n − s ) = a − ⌊ n 2 ⌋ − s \left\lceil \dfrac{n}{2} \right\rceil + (a - n - s) = a - \left\lfloor \dfrac{n}{2} \right\rfloor - s ⌈2n⌉+(a−n−s)=a−⌊2n⌋−s;

综上,操作次数为 a − ⌊ n 2 ⌋ − s a - \left\lfloor \dfrac{n}{2} \right\rfloor - s a−⌊2n⌋−s。

于是令 k = a − ⌊ n 2 ⌋ − s k = a - \left\lfloor \dfrac{n}{2} \right\rfloor- s k=a−⌊2n⌋−s,得到 s = a − ⌊ n 2 ⌋ − k . s = a - \left\lfloor \dfrac{n}{2} \right\rfloor - k. s=a−⌊2n⌋−k.

接下来只要验证这个解是否满足条件。

  • 当 n n n 为偶数,需要满足 s ≤ ⌊ a − n 2 ⌋ s \leq \left\lfloor \dfrac{a - n}{2} \right\rfloor s≤⌊2a−n⌋;
    • 当 a a a 为偶数,左式 s = a − n 2 − k s = a - \dfrac{n}{2} - k s=a−2n−k,右式 a − n 2 \dfrac{a - n}{2} 2a−n,作差得到 a 2 − k = ⌈ a 2 ⌉ − k ≤ 0 \dfrac{a}{2} - k = \left\lceil \dfrac{a}{2} \right\rceil - k \leq 0 2a−k=⌈2a⌉−k≤0
    • 当 a a a 为奇数,左式 a − n 2 − k a - \dfrac{n}{2} - k a−2n−k,右式 a − n − 1 2 \dfrac{a - n - 1}{2} 2a−n−1,作差得到 a + 1 2 − k = ⌈ a 2 ⌉ − k ≤ 0 \dfrac{a + 1}{2} - k = \left\lceil \dfrac{a}{2} \right\rceil - k \leq 0 2a+1−k=⌈2a⌉−k≤0;
  • 当 n n n 为奇数,需要满足 s ≤ ⌈ a − n 2 ⌉ s \leq \left\lceil\dfrac{a - n}{2} \right\rceil s≤⌈2a−n⌉;
    • 当 a a a 为奇数,左式 a − n − 1 2 − k a - \dfrac{n - 1}{2} - k a−2n−1−k,右式 a − n 2 \dfrac{a - n}{2} 2a−n,作差得到 a + 1 2 − k = ⌈ a 2 ⌉ − k ≤ 0 \dfrac{a + 1}{2} - k = \left\lceil \dfrac{a}{2} \right\rceil - k \leq 0 2a+1−k=⌈2a⌉−k≤0;
    • 当 a a a 为偶数,左式 a − n − 1 2 − k a - \dfrac{n - 1}{2} - k a−2n−1−k,右式 a − n + 1 2 \dfrac{a - n + 1}{2} 2a−n+1,作差得到 a 2 − k = ⌈ a 2 ⌉ − k ≤ 0 \dfrac{a}{2} - k = \left\lceil \dfrac{a}{2} \right\rceil - k \leq 0 2a−k=⌈2a⌉−k≤0;

综上,解 s = a − ⌊ n 2 ⌋ − k s = a - \left\lfloor \dfrac{n}{2} \right\rfloor - k s=a−⌊2n⌋−k 合法。

那么额外分配给怪物 1 1 1 的为 a − n − s = k − ⌈ n 2 ⌉ a - n - s = k - \left\lceil \dfrac{n}{2} \right\rceil a−n−s=k−⌈2n⌉,怪物 2 2 2 的为 a − ⌊ n 2 ⌋ − k a - \left\lfloor \dfrac{n}{2} \right\rfloor - k a−⌊2n⌋−k。

C++ Code

cpp 复制代码
#include <bits/stdc++.h>

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, a, k;
    std::cin >> n >> a >> k;
    
    if (n == 1) {
        std::cout << (a == k ? a: -1) << "\n";
        return 0;
    }
    if ((a + 1) / 2 > k or a - n / 2 < k) {
        std::cout << -1 << "\n";
        return 0;
    }
    
    std::vector ans(n, 1);
    ans[0] += k - (n + 1) / 2;
    ans[1] += a - k - n / 2;
    
    for (int i = 0; i < n; i++) {
        std::cout << ans[i] << " \n"[i == n - 1];
    }
    
    return 0;
}
相关推荐
算法熔炉4 小时前
深度学习面试八股文(2)——训练
人工智能·深度学习·算法
EXtreme354 小时前
【数据结构】打破线性思维:树形结构与堆在C语言中的完美实现方案
c语言·数据结构·算法··heap·完全二叉树·topk
cici158744 小时前
含风电场的十机24时系统机组出力优化算法
人工智能·算法·机器学习
WolfGang0073214 小时前
代码随想录算法训练营Day45 | 101.孤岛的总面积、102.沉没孤岛、103.水流问题、104.建造最大岛屿
算法·深度优先
2301_764441334 小时前
PMC政策文本量化评估
python·算法·信息可视化
代码游侠5 小时前
应用——Linux进程编程实例分析
linux·运维·网络·笔记·学习·算法
羑悻的小杀马特5 小时前
C++多线程同步工具箱:call_once精准触发、lock_guard/unique_lock智能管理,打造无死锁程序!
c++·多线程·死锁·lock_guard·unique_lock·call_once
电子_咸鱼5 小时前
【QT——信号和槽(1)】
linux·c语言·开发语言·数据库·c++·git·qt
DuHz5 小时前
《Around the Corner mmWave Imaging in Practical Environments》论文精读
论文阅读·算法·信息与通信·毫米波雷达