1 条题解
-
0
思路
设选中的 个不同水平依次为 。整数互不相同意味着 ,题目又要求 ,所以必须恰好满足 。这些水平就是从 开始的连续 个整数。
将相同水平的学生归为一组。对于一个合法等级段,每个等级都恰好选择一名学生。若这些等级分别有 名学生,按照乘法原理,该等级段贡献 种不同学生集合。
做法
将所有水平排序并压缩,得到严格递增的水平序列 及对应人数 。依次考察压缩后长度恰好为 的窗口。由于水平已经互异,窗口合法当且仅当最大水平减最小水平严格小于 。
令模数 ,建立人数的前缀乘积 、。一个窗口 的人数乘积等于 。
每个频率都在 到 之间,而 ,所以频率在模 下非零。素数域中非零数的乘积仍非零,因此每个前缀乘积都有逆元。先用快速幂求出最后一个前缀乘积的逆元,再用 从后向前求出全部逆元。
枚举每个合法窗口,用上述式子计算贡献并加入答案,每一步都对 取模。
正确性证明
任何合法舞蹈选出的水平都是连续的 个整数,所以压缩后的水平序列中存在唯一一个长度为 的窗口与其对应。反过来,压缩序列中极差小于 的窗口恰好包含连续的 个等级;从各等级任取一人,得到的学生集合均满足题意。
在同一个窗口中,各等级的选人相互独立,贡献等于人数乘积。两个窗口的水平集合不同,因此不可能代表同一个学生集合。算法恰好枚举所有合法窗口,正确计算每个窗口的贡献,且不会重复计数,故总和就是答案。
部分分做法
子任务 1 直接枚举学生编号的所有 元集合,再逐对检查水平是否不同、差值是否小于 。这是对原题定义的直接枚举。
子任务 2 同样将学生按水平分组,但不预处理逆元。对每个合法窗口,重新逐项相乘得到贡献,时间复杂度为 。
子任务 3 中所有水平互异,每个合法窗口的贡献都是 。排序后只需统计极差小于 的窗口数量,无需处理带重数选择和模乘法逆元。
一般情形使用前缀乘积与逆元。也可以用维护区间乘积的数据结构,或用两个栈组成维护滑动乘积的队列,从而避免模除法。
复杂度
排序需要 时间。压缩、前缀乘积、逆元逆推和窗口扫描均为 ;一次快速幂需要 。每组总时间为 ,额外空间为 。
集合枚举的时间复杂度为 ,递归与所选集合占用 空间。逐窗口乘法为 时间、 空间;水平互异分支为 时间、 空间。
模乘法中间结果可能超过 32 位整数范围,应使用 64 位整数,并在每次乘法后及时取模。
信息
- ID
- 1694
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者