1 条题解

  • 0
    @ 2026-9-3 10:57:12

    DSU Master:题解

    思路

    固定前缀长度 kk。如果 aj=0a_j=0,边 jj 有机会向当前包含顶点 11 的汇点连入一条边;如果 aj=1a_j=1,它不会产生这种贡献。

    记

    f1=1,fi+1=fi(i−ai).f_1=1,\qquad f_{i+1}=f_i(i-a_i).

    fif_i 表示在只看前 i−1i-1 条边的相对顺序时,顶点 11 在处理边 ii 前仍是所在连通块汇点的有效排列数。加入边 ii 后:若 ai=0a_i=0,原有 ii 个插入位置都保持汇点,故乘 ii;若 ai=1a_i=1,恰有一个插入位置会使顶点 11 不再是汇点,故乘 i−1i-1。这正是 i−aii-a_i。

    令 ansians_i 为题目要求的长度为 ii 的所有排列的值之和。把新边 ii 插入旧排列:旧贡献在 ii 个插入位置中各出现一次,得到 i ansi−1i\,ans_{i-1};当且仅当 ai=0a_i=0 时,还新增 fif_i 条指向顶点 11 的边。因此

    ans0=0,ansi=i ansi−1+[ai=0]fi.ans_0=0,\qquad ans_i=i\,ans_{i-1}+[a_i=0]f_i.

    两条递推都可在线性时间维护。

    做法

    满分做法按输入顺序维护 ff 与 ansans。读入 aia_i 后,先用当前 fif_i 更新并输出 ansians_i,再计算 fi+1=fi(i−ai)f_{i+1}=f_i(i-a_i)。

    子任务算法

    • 子任务 1:枚举每个 kk 的全部 k!k! 个排列,按题意用并查集模拟有向合并。
    • 子任务 2:先计算所有 fif_i,再对每个 kk 显式求和 ∑j=1k[aj=0]fj k!/j!\sum_{j=1}^k[a_j=0]f_j\,k!/j!,复杂度 O(n2)O(n^2)。
    • 子任务 3:使用上述两个滚动递推,复杂度 O(n)O(n)。

    正确性证明

    引理 1:fif_i 等于处理边 ii 前顶点 11 仍为所在连通块汇点的有效相对顺序数。

    证明:f1=1f_1=1。将边 ii 插入已有顺序时共有 ii 个位置。若 ai=0a_i=0,它指向左侧汇点,所有位置都保留顶点 11 为汇点;若 ai=1a_i=1,恰有一个位置使右侧汇点接管,只有 i−1i-1 个位置有效。因此转移为 fi+1=fi(i−ai)f_{i+1}=f_i(i-a_i)。归纳成立。

    引理 2:ansi=i ansi−1+[ai=0]fians_i=i\,ans_{i-1}+[a_i=0]f_i。

    证明:把新边 ii 插入每个长度 i−1i-1 的排列,共有 ii 个位置,所以既有入边贡献被重复 ii 次。新边仅在 ai=0a_i=0 且顶点 11 仍为汇点时贡献一条入边,这类排列由引理 1 恰有 fif_i 个。故递推成立。

    定理:算法输出每个 kk 的正确答案。

    证明:由引理 2,从 ans0=0ans_0=0 依次计算得到的 anskans_k 恰为全部 k!k! 个排列的值之和;所有运算按模数进行,不改变模意义答案。

    复杂度

    每组测试时间复杂度 O(n)O(n),空间复杂度 O(1)O(1);所有测试合计为 O(∑n)O(\sum n)。

    • 1

    信息

    ID
    1368
    时间
    2000ms
    内存
    512MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者