1 条题解

  • 0
    @ 2026-5-18 19:50:13

    D1. 青年飞机制造者俱乐部(简单版本)详细题解

    问题理解

    有一栋 nn 层的楼,每层一个人。他们要发射 mm 架纸飞机,发射顺序已知(但 easy version 中全部丢失,即所有 ai=0a_i = 0)。

    规则:

    • 当第 ii 层的人发射一架飞机时,11ii 层的人都能看到。
    • 如果某层的人已经看到了至少 cc 架飞机,他就不再发射。
    • 最终,每层的人至少看到 cc 架飞机,且总共发射 mm 架。

    问:有多少种方式填补空缺(给每架飞机指定发射楼层),使得规则成立。


    核心简化

    因为所有 ai=0a_i = 0,我们只需决定 每层最终发射了多少架飞机,而不关心具体顺序(只要存在一种顺序满足“看到 cc 架就停止”的约束)。

    xix_i = 第 ii 层发射的飞机数。则:

    • xi0x_i \ge 0,且 xicx_i \le c(因为一旦看到 cc 架就停止,不可能发射超过 cc 架?不对,xix_i 可以等于 cc,但不能超过)
    • 最终每层看到的飞机数 = j=1ixjc\sum_{j=1}^{i} x_j \ge c(第 ii 层看到的是前 ii 层的总和)
    • 总发射数 i=1nxi=m\sum_{i=1}^{n} x_i = m

    顺序可行性条件

    仅仅满足上面的不等式还不够,还需要存在一种发射顺序,使得每个人在发射过程中不会违反“看到 cc 架后停止”。

    实际上,可以证明:只要 xicx_i \le cj=1ixjc\sum_{j=1}^{i} x_j \ge c 对所有 ii 成立,就一定存在一种顺序

    构造方法:从高层到低层安排发射。因为高层的人看到的是所有低层 + 自己,只要低层先发射够 cc 架,高层再发射即可。

    更严谨地说:可行的充要条件是

    j=1ixjci\sum_{j=1}^{i} x_j \ge c \quad \forall i

    xicix_i \le c \quad \forall i

    转化为组合计数

    问题变为:求非负整数解 (x1,,xn)(x_1, \dots, x_n) 的数量,满足:

    1. 0xic0 \le x_i \le c
    2. i=1nxi=m\sum_{i=1}^{n} x_i = m
    3. j=1ixjc\sum_{j=1}^{i} x_j \ge c 对所有 ii 成立

    条件 3 的等价形式

    Si=j=1ixjS_i = \sum_{j=1}^{i} x_j。则 S0=0S_0 = 0Sn=mS_n = m,且 SicS_i \ge c 对所有 i1i \ge 1

    另外,xi=SiSi1x_i = S_i - S_{i-1},所以 0SiSi1c0 \le S_i - S_{i-1} \le c

    因此,这是一个关于 SiS_i 的路径计数问题:

    • S0=0S_0 = 0
    • Sn=mS_n = m
    • SiS_i 非降,且 SiSi1[0,c]S_i - S_{i-1} \in [0, c]
    • SicS_i \ge c 对所有 i1i \ge 1

    重新参数化

    Ti=SicT_i = S_i - c。则:

    • T0=cT_0 = -c
    • Tn=mcT_n = m - c
    • TiTi1=xi[0,c]T_i - T_{i-1} = x_i \in [0, c]
    • 条件 SicS_i \ge c 等价于 Ti0T_i \ge 0 对所有 i1i \ge 1

    T0=c<0T_0 = -c < 0,所以路径从负数出发,走到 mcm-c,且每一步增量在 [0,c][0,c],并且除了起点外所有点 0\ge 0


    使用反射原理(Ballot 定理)

    这是一个经典的“不穿过零”的路径计数问题。可以用组合数学中的 反射法容斥 解决。

    但标程直接用 DP:

    $$dp[i][j] = \text{前 } i \text{ 层共发射 } j \text{ 架飞机的方案数} $$

    转移:

    dp[i][j]=k=0min(c,j)dp[i1][jk]dp[i][j] = \sum_{k=0}^{\min(c, j)} dp[i-1][j-k]

    其中 kk 是第 ii 层发射的飞机数。

    初始:dp[0][0]=1dp[0][0] = 1
    答案:dp[n][m]dp[n][m]

    这个 DP 等价于:将 mm 拆分成 nn 个非负整数,每个 c\le c,的方案数。


    为什么不需要额外约束 j=1ixjc\sum_{j=1}^{i} x_j \ge c

    因为当所有 xicx_i \le c 且总和 =mc= m \ge c 时,前缀和 c\ge c 不一定自动成立。例如 n=2,c=3,m=3n=2,c=3,m=3x=(0,3)x=(0,3),则 S1=0<3S_1=0<3,不满足。

    所以标程的 DP 是 错误的?但示例中 n=3,c=2,m=4n=3,c=2,m=4,DP 结果:

    • 把 4 拆成 3 个 2\le 2 的数:(2,2,0),(2,0,2),(0,2,2),(2,1,1),(1,2,1),(1,1,2)(2,2,0),(2,0,2),(0,2,2),(2,1,1),(1,2,1),(1,1,2) 共 6 种,恰好是答案。

    检查 (2,0,2)(2,0,2)S1=22S_1=2\ge2, S2=22S_2=2\ge2, S3=42S_3=4\ge2,满足。
    (0,2,2)(0,2,2)S1=0<2S_1=0<2,不满足!为什么这个会被计入 DP?

    (0,2,2)(0,2,2) 对应第 1 层发射 0 架,第 2 层发射 2 架,第 3 层发射 2 架。
    第 1 层的人看到 0 架,但要求至少看到 c=2c=2 架,矛盾。所以这个序列不合法。

    但示例输出 6,而上面列出的 6 个序列中,(0,2,2)(0,2,2)(0,2,2)(0,2,2) 的排列?实际上正确列表是: [1,1,3,3][1,1,3,3] 对应 x=(2,0,2)x=(2,0,2)?不对,[1,1,3,3][1,1,3,3] 表示第 1,2 架由 1 层发射,第 3,4 架由 3 层发射,则 x1=2,x2=0,x3=2x_1=2,x_2=0,x_3=2,和 (2,0,2)(2,0,2) 一样,合法。
    [2,2,3,3][2,2,3,3] 对应 x=(0,2,2)x=(0,2,2),但示例中确实有 [2,2,3,3][2,2,3,3] 吗?示例列表中是 [2,2,3,3][2,2,3,3],对应 x1=0,x2=2,x3=2x_1=0,x_2=2,x_3=2,不满足 S12S_1\ge2,为什么被列入?

    仔细看示例列表:[2,2,3,3][2,2,3,3] 是有效的吗?

    • 第 1 架由 2 层发射:此时 1 层人看到 1 架(因为 1 层看不到 2 层的飞机?不对,1 层能看到 2 层发射的飞机吗?规则:第 i 层发射时,1~i 层都能看到。所以 2 层发射时,1 层也能看到。所以第 1 架后,1 层看到 1 架,2 层看到 1 架。
    • 第 2 架由 2 层发射:1 层看到 2 架(已到 c),2 层看到 2 架(已到 c)。
    • 此后 1 层不再发射(已到 c),2 层也不再发射。
    • 第 3,4 架由 3 层发射:3 层发射时,1,2,3 层都能看到。此时 1 层已看到 2 架,不会再发射,但看到新飞机不影响规则。
      最终,1 层看到 4 架,2 层看到 4 架,3 层看到 2 架,都 ≥2。所以 [2,2,3,3][2,2,3,3] 实际上满足条件!

    为什么我之前的 S1=0S_1=0 判断错误?因为 x1x_1 是 1 层发射数,但 1 层看到的飞机 = 所有楼层 ≤1 的发射数 = x1x_1,确实是 0。但这里 1 层看到了来自 2 层的飞机,所以 S1S_1 的定义应该是 1 层看到的飞机总数,而不是 1 层发射的飞机数。我之前混淆了。


    正确的前缀和定义

    sis_i = 第 ii 层最终看到的飞机总数 = 所有楼层 ≤ i 的发射数之和 = j=1ixj\sum_{j=1}^{i} x_j

    那么条件 sics_i \ge c 对所有 i 成立。

    [2,2,3,3][2,2,3,3] 例子中:

    • x1=0,x2=2,x3=2x_1=0, x_2=2, x_3=2
    • s1=x1=0s_1 = x_1 = 0 ???不对,1 层看到的飞机包括来自 2 层的吗?规则:当第 2 层发射时,1 层能看到。所以 s1s_1 应该等于所有由楼层 ≤1 发射的飞机数?还是等于所有能被 1 层看到的飞机数?

    1 层能看到的飞机 = 所有楼层 ≤1 的发射数?不对,1 层能看到所有楼层发射的飞机,因为任何楼层发射时,1 层都在其下方(i≥1 时,1 层都能看到)。所以 1 层能看见所有飞机!

    因此 sis_i = 所有楼层 ≤ i 的发射数?不对,i 层能看到的是所有楼层 ≥ i?不,规则:第 i 层发射时,1~i 层能看到。所以 i 层能看到的 = 所有楼层 j 满足 j ≥ i 的发射数?因为当 j 层发射时,i 层能看到当且仅当 i ≤ j。

    所以第 i 层能看到的飞机 = 所有楼层 j ≥ i 的发射数之和!

    ti=j=inxjt_i = \sum_{j=i}^{n} x_j = 从 i 层及以上发射的总数。
    那么第 i 层看到的飞机数 = tit_i

    条件:tict_i \ge c 对所有 i。

    t1=mct_1 = m \ge ctn+1=0t_{n+1}=0titi+1=xi[0,c]t_i - t_{i+1} = x_i \in [0,c]

    所以这是一个关于 tit_i 的下降路径:t1=mt_1 = mtn+1=0t_{n+1}=0titi+1[0,c]t_i - t_{i+1} \in [0,c],且 tict_i \ge c 对所有 i(除了 i=n+1 时 0 可能 < c)。


    重新参数化

    ui=ticu_i = t_i - c,则 u1=mcu_1 = m-cun+1=cu_{n+1} = -cuiui+1=xi[0,c]u_i - u_{i+1} = x_i \in [0,c],且 ui0u_i \ge 0 对所有 i 从 1 到 n。

    这是一个从 mcm-c 走到 c-c 的路径,每步减 [0,c][0,c],且中间点非负。


    反射法解决

    这种路径计数等价于:将 mm 拆成 nn 个非负整数 c\le c 且前缀和(从高到低)≥ c 的方案数。
    这和 DP 等价,但标程的 DP 为什么能直接算?

    经过推导,当所有 xicx_i \le cmcm \ge c 时,条件 tict_i \ge c 自动等价于 x1++xi1mcx_1 + \dots + x_{i-1} \le m-c?不。

    实际上,标程的 DP 算的是 把 m 拆成 n 个 ≤c 的非负整数的方案数,这恰好等于本题的答案。为什么?因为条件 tict_i \ge c 对于所有 i 等价于 x1++xi1mcx_1 + \dots + x_{i-1} \le m-c,而 xicx_i \le c 自然满足后,这个条件其实自动成立?检查 (0,2,2)(0,2,2)m=4,c=2m=4,c=2x1=02x_1=0 \le 2x1+x2=2mc=2x_1+x_2=2 \le m-c=2,满足,所以合法。之前认为不合法是错的。

    所以实际上 条件自动满足,只要每个 xicx_i \le c 且总和 =mc=m \ge c,就能找到顺序。因此答案就是整数拆分数。


    结论

    在 easy version 中,答案 = 将 mm 拆成 nn 个非负整数,每个不超过 cc 的方案数。

    DP 公式:

    dp[i][j]=k=0min(c,j)dp[i1][jk]dp[i][j] = \sum_{k=0}^{\min(c,j)} dp[i-1][j-k]

    初始 dp[0][0]=1dp[0][0]=1,答案 dp[n][m]dp[n][m]

    时间复杂度 O(nmc)O(n \cdot m \cdot c),空间 O(m)O(m) 可优化。


    示例验证

    n=3,c=2,m=4n=3,c=2,m=4,DP 得 6,符合输出。


    最终答案

    所以这道题就是一个经典的 有上限的整数拆分 计数,用简单的 DP 即可解决。

    • 1

    青年飞机制造者俱乐部(简单版本)

    信息

    ID
    7219
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者