1 条题解

  • 0
    @ 2026-9-9 22:22:13

    思路

    设选中的 mm 个不同水平依次为 b1<b2<⋯<bmb_1<b_2<\cdots<b_m。整数互不相同意味着 bm−b1≥m−1b_m-b_1\ge m-1,题目又要求 bm−b1<mb_m-b_1<m,所以必须恰好满足 bm−b1=m−1b_m-b_1=m-1。这些水平就是从 b1b_1 开始的连续 mm 个整数。

    将相同水平的学生归为一组。对于一个合法等级段,每个等级都恰好选择一名学生。若这些等级分别有 c1,c2,…,cmc_1,c_2,\ldots,c_m 名学生,按照乘法原理,该等级段贡献 c1c2⋯cmc_1c_2\cdots c_m 种不同学生集合。

    做法

    将所有水平排序并压缩,得到严格递增的水平序列 vv 及对应人数 cc。依次考察压缩后长度恰好为 mm 的窗口。由于水平已经互异,窗口合法当且仅当最大水平减最小水平严格小于 mm。

    令模数 P=109+7P=10^9+7,建立人数的前缀乘积 p0=1p_0=1、pi+1=pici mod Pp_{i+1}=p_i c_i\bmod P。一个窗口 [l,l+m)[l,l+m) 的人数乘积等于 pl+mpl−1 mod Pp_{l+m}p_l^{-1}\bmod P。

    每个频率都在 11 到 nn 之间,而 n<Pn<P,所以频率在模 PP 下非零。素数域中非零数的乘积仍非零,因此每个前缀乘积都有逆元。先用快速幂求出最后一个前缀乘积的逆元,再用 pi−1=cipi+1−1 mod Pp_i^{-1}=c_i p_{i+1}^{-1}\bmod P 从后向前求出全部逆元。

    枚举每个合法窗口,用上述式子计算贡献并加入答案,每一步都对 PP 取模。

    正确性证明

    任何合法舞蹈选出的水平都是连续的 mm 个整数,所以压缩后的水平序列中存在唯一一个长度为 mm 的窗口与其对应。反过来,压缩序列中极差小于 mm 的窗口恰好包含连续的 mm 个等级;从各等级任取一人,得到的学生集合均满足题意。

    在同一个窗口中,各等级的选人相互独立,贡献等于人数乘积。两个窗口的水平集合不同,因此不可能代表同一个学生集合。算法恰好枚举所有合法窗口,正确计算每个窗口的贡献,且不会重复计数,故总和就是答案。

    部分分做法

    子任务 1 直接枚举学生编号的所有 mm 元集合,再逐对检查水平是否不同、差值是否小于 mm。这是对原题定义的直接枚举。

    子任务 2 同样将学生按水平分组,但不预处理逆元。对每个合法窗口,重新逐项相乘得到贡献,时间复杂度为 O(nlog⁡n+nm)O(n\log n+nm)。

    子任务 3 中所有水平互异,每个合法窗口的贡献都是 11。排序后只需统计极差小于 mm 的窗口数量,无需处理带重数选择和模乘法逆元。

    一般情形使用前缀乘积与逆元。也可以用维护区间乘积的数据结构,或用两个栈组成维护滑动乘积的队列,从而避免模除法。

    复杂度

    排序需要 O(nlog⁡n)O(n\log n) 时间。压缩、前缀乘积、逆元逆推和窗口扫描均为 O(n)O(n);一次快速幂需要 O(log⁡P)O(\log P)。每组总时间为 O(nlog⁡n+log⁡P)O(n\log n+\log P),额外空间为 O(n)O(n)。

    集合枚举的时间复杂度为 O((nm)m2)O(\binom{n}{m}m^2),递归与所选集合占用 O(n)O(n) 空间。逐窗口乘法为 O(nlog⁡n+nm)O(n\log n+nm) 时间、O(n)O(n) 空间;水平互异分支为 O(nlog⁡n)O(n\log n) 时间、O(n)O(n) 空间。

    模乘法中间结果可能超过 32 位整数范围,应使用 64 位整数,并在每次乘法后及时取模。

    • 1

    信息

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