241118 noip 数数模拟赛
省流:\(100 + 100 + 100 + 10\)。四道数数太好玩了。绿蓝紫黑。
T1
题意:
如下是一个不完全正确的归并排序算法代码。
其中,主函数内将使用如下方法调用排序:
初始给定一个 \(n\) 表示你要给一个长度为 \(n\) 的排列进行排序,多次询问,每次给定一个 \(k\),你需要求出有多少种排列能够用上面的代码排序成单调递增的,对 \(998244353\) 取模。
\(T \leq 100,n \leq 5 \times 10^6,k \leq 10^9\)。
容易发现,对于一个 \(k\) 和一个排列,第 \(k\) 层的每个区间内排列中的数字都单调递增,则这个排列是可以排序好的。设第 \(k\) 层的区间为 \([l_1,r_1],[l_2,r_2],\cdots,[l_m,r_m]\)(这些区间并为 \([1,n]\),交为空),那么合法的排列个数即为 \(\frac{n}{\prod_{i = 1}^m r_i - l_i + 1}\)。容易发现同一层中区间不同长度至多为 \(2\),所以可以递推得出第 \(k\) 层中长度为 \(x\) 的有多少个区间,计算上述柿子即可。对于 \(k > \log n\),那么不管什么排列都合法,输出 \(n!\) 即可。
时间复杂度 \(\Theta(n + T)\)。
代码:
T2
题意:给定正整数 \(n,m\),以及长度为 \(m\),值域为 \([0,n−1]\) 的整数序列 \(a_1,a_2,\cdots,a_m\)。保证 \(a\) 中元素互不相同。
你需要计算满足以下要求的 \(0,1,…,n − 1\) 的排列 \(p\) 的数量:
-
能够经过任意次以下操作,使 \(p=a\):
- 选择 \(1 \leq l \leq r\leq \lvert p \rvert\) 的两个数 \(l,r\),如果 \(\text{mex}({p_l,p_{l + 1},…,p_r})\) 存在于序列 \(p\) 中,则将 \(p_l,p_{l + 1},\cdots,p_r\) 删除。
输出答案对 \(998244353\) 取模后的结果。
\(1 \leq m \leq n \leq 10^6,\sum m \leq 10^6,0 \leq a_i <n\),\(a\) 中元素互不相同。
注意,\(\sum a\) 没有限制。
将排列 \(p\) 合法的要求转换一下,设 \(a\) 中最小的元素为 \(mn\),设 \(l,r\) 为对于 \(p\) 中所有 \(<mn\) 的元素位置最小和最大的位置是什么,则合法要求为 \(p\) 中 \(a\) 的元素按照顺序且不存在一个 \(a\) 中的元素它的位置 \(>l\) 且 \(<r\)。
我们可以先钦定 \(mn + m\) 个位置表示这些位置用来放 \(<mn\) 的元素和 \(a\) 中的元素,方案数为 \(C_n^{mn + m}\),由于 \(a\) 中的元素不能 \(>l\) 且 \(<r\),所以对于这 \(mn + m\) 个位置分配的方案数为 \(m + 1\),由于 \(<mn\) 的元素可以乱序,方案数为 \(mn!\),最后再把剩下的 \(n - mn - m\) 放进去,方案数为 \((n - mn - m)!\),把以上所有的方案数相乘即是答案。\(mn \leq 1\) 可能需要特判。
时间复杂度 \(\Theta(n + \sum m)\)。
代码:
T3
题意:给定一张 \(n\) 个点 \(m\) 条边的图和一个定值 \(k\),你需要对所有的 \(0 \leq i \leq k\) 求出只保留 \(n - 1 + i\) 条边且图还连通的选边方案数,对 \(998244353\) 取模。
\(n \leq 17,0 \leq k \leq 2\)。
这个 \(k\) 的范围非常有迷惑性,实际上树和基环树的性质完全没有用。
可以设计状压 dp,设 \(dp_{state,0/1/2}\),表示当前已经连通了 \(state\) 的二进制位中为 \(1\) 的点,且保留了 \(\text{popcount}(state) + 0/1/2\) 条边。转移如下:
\(cnt_{s,t}\) 表示一个端点在 \(s\) 中,另一个端点在 \(t\) 中的边的个数。
发现这会算重,但是容易发现上述的 dp 对于一个有 \(i\) 条边的图,对于每一条边都会给答案加上这张图的贡献,所以让 \(dp_{state,0}\) 除以 \(\text{popcount}(state)-1\),\(dp_{state,1/2}\) 同理即可。
这样我们就得到了一个 \(\Theta(3^n n^2)\) 的做法。考虑优化,发现一条边两个端点有一个不在 \(state\) 中,那么这条边无论如何都不会算到,可以暴力算出有可能被算到的边,记数量为 \(sum\),如果一条边两个端点都在 \(state\) 中但却没有计算到当且仅当两个端点都在 \(s\) 或 \(state \oplus s\),于是先预处理高维前缀和,这样我们就可以快速的求出 \(cnt_{s,t} = sum - tot_s - tot_t\)。
时间复杂度 \(\Theta(2^n n + 3^n)\)。
代码:
闲话:这题其实没有 \(100\),被卡常了,但是通过死缠烂打让教练把时限开到了 2s 于是过了/kx
T4
原题:qoj8143。
首先暴力求出 \(\sum_{i=1}^b f(a,b,i)\),接下来讨论 \(i > b\) 的情况。
若 \(a \mid b\),则 \(i > b\) 时答案为 \(\frac{b}{a}\),接下来不做讨论(即不讨论下文方程中 \(y = 0\) 的情况)。
显然 \(f(a,b,i)\) 为方程 \(ax + iy = b\) 的解中最小的非负整数解 \(x\),将方程变形为 \(x = \frac{b − iy}{a}(x \geq 0)\)。由于 \(i>b\),有 \(\lvert iy \rvert > b\),又因为 \(x \geq 0\),所以 \(y < 0\)。设 \(z = −y(z > 0)\),则 \(x=\frac{b + iz}{a}\),由于最小化 \(x\),则 \(z\) 取 \(f(i,−b,a)\)。发现若 \((i ~\text{mod}~ a)\) 相同时,取得的 \(z\) 也相同。枚举 \((i ~\text{mod}~ a)\),等差数列求和即可。
设 \(l = a + b\),单组数据总时间复杂度 \(\Theta(l \log l)\)。
代码:
__EOF__

本文链接:https://www.cnblogs.com/System-Error/p/18552910.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探