MX 炼石 2025 NOIP #5

串串好次。

笑点解析:这到底是哪一年的炼石计划。



2025 --【炼石计划 NOIP】-- 第五套

链接:link
题解:link

时间:4h (2025.09.11 14:00~18:00)
题目数:4
难度:

A B C D
\(\color{#52C41A} 绿\) \(\color{#52C41A} 绿\) \(\color{#9D3DCF} 紫\) \(\color{#BFBFBF} ?\)
*1900 *1700 *2700 *?

估分:60 + 80 + 32 + ? = 172+?
得分:40 + 60 + 32 + 10 = 142
Rank:42/216


场祭

读题。怎么两道串串题。

开 A,期望 dp,推了一会儿发现可以令 \(f_{i,j}\) 表示第 \(i\) 个时刻有 \(j\) 个人选 A 的概率,转移:

\[f_{i,j} = \frac {j-1} {n+i-1} f_{i-1,j-1} + \frac {n+i-1-j} {n+i-1} f_{i-1,j} \]

答案就是概率乘上贡献。这样是 \(O(nm)\) 的而且发现非常不好优化,数据结构做不了,只维护后缀和也做不了。于是就这么写了个暴力走人了。

大概有 80pts 吧,如果不卡常的话。

B 一眼 KMP,但是发现要维护 fail 树的子树大小支持动态加叶子,显然是 LCT 但是我不会,于是只打了 60pts 的暴力和 20pts 的离线 dsu on tree。

还剩 1h+。

C 先把 32pts 的暴力打了。然后找性质,发现 \(k=2\) 时每个 \(0 \sim 2^k - 1\) 的序列都是 \(0 \sim 2^{k-1} - 1\) 的序列后面拼上自己的按位取反之后的结果,但是不知道有啥用。

D 性质 A 分这么多,不过好像很多细节比较麻烦,没时间了直接 random_shuffle 相信随机数吧。应该是可以有分的。


补题

草草草,A 只得了 40pts,多测 \(\sum n + \sum m\) 太大导致的,早知道就直接预处理所有 \(n\) 的答案了,起码能多拿 10pts。

A 还有逆天注意力做法……注意到如果稍微换一下 dp 状态,令 \(f_{i,j}\) 为一共有 \(i\) 个人,\(j\) 个不选 A 的概率,那么:

\[\begin{aligned} f_{n,n-1} & = 1 \\ \frac j i f_{i,j} & \to f_{i+1,j+1} \\ \frac {i-j} i f_{i,j} & \to f_{i+1,j} \end{aligned} \]

观察到:

\[f_{i,j} = \frac {\binom {j-1} {n-2}} {\binom {i-1} {n-1}} \]

于是答案:

\[\begin{aligned} & \sum _{i=n+1} ^{n+m} \sum _{j=1} ^i f_{i,j} \times \max(0,2(i-j)-i) \\ = & \sum _{i=n+1} ^{n+m} \sum _{j = 1} ^{\lfloor \frac i 2 \rfloor} \frac {\binom {j-1} {n-2}} {\binom {i-1} {n-1}} \times (i-2j) \\ = & \sum _{i=n+1} ^{n+m} \frac 1 {\binom {i-1} {n-1}} \sum _{j = 1} ^{\lfloor \frac i 2 \rfloor} \binom {j-1} {n-2} \times (i-2j) \\ = & \sum _{i=n+1} ^{n+m} \frac 1 {\binom {i-1} {n-1}} \left( i \sum _{j = 1} ^{\lfloor \frac i 2 \rfloor} \binom {j-1} {n-2} - \sum _{j = 1} ^{\lfloor \frac i 2 \rfloor} \binom {j-1} {n-2} 2j \right) \end{aligned} \]

直接前缀和算一下后面拿两个 \(\sum\) 就好了。注意到 \(n=1\) 需要特判。

但是我们不具有这样的观察力,所以考虑组合意义。

直接做不可以,因为每种情况的概率不相同。

考虑转化。首先我们还是要求一共有 \(i\) 个人,\(j\) 个不选 A 的概率。先把 \(n\) 个选手放到一个序列上,编号分别为 \(\color{#66CCFF} 1 \sim n\)

\[{\color{#66CCFF}1} , {\color{#66CCFF}2} , {\color{#66CCFF}3} , \ldots , {\color{#66CCFF}n} \]

然后每加入一个观众 \({\color{#EEAADD}i}\),就相当于在当前序列中任选一个位置,把 \({\color{#EEAADD}i}\) 插入这个位置后面,例如:

\[{\color{#66CCFF}1} , {\color{#EEAADD} n+1} , {\color{#EEAADD} n+3} , {\color{#66CCFF}2} , {\color{#EEAADD} i} , {\color{#66CCFF}3} , \ldots , {\color{#66CCFF}n} , {\color{#EEAADD} n+2} \]

可以发现,最终形成的是一个 \({\color{#66CCFF}1} \sim {\color{#EEAADD}i}\) 的排列,其中 \(\color{#66CCFF} 1 \sim n\)\(n\) 个数相对有序。显然这样形成的每个序列和每种情况构成双射,且出现的概率相同。

然后计数:

  • 总方案数:
    • 我们钦定 \(\color{#66CCFF}1\) 在首位,为了使 \(\color{#66CCFF} 1 \sim n\) 相对有序,需要在剩下 \(i-1\) 个位置里选择 \(n-1\) 个来放 \(\color{#66CCFF} 2 \sim n\),方案数也就是 \(\binom {i-1} {n-1}\)
    • 剩下的 \(i-n\) 个元素 \(\color{#EEAADD} n+1 \sim i\) 则可以任意排列,方案数为 \((i-n)!\)
    • 容易发现这样计数是不重不漏的,所以总方案数即为 \(\binom {i-1} {n-1} \times (i-n)!\)
  • 合法方案数:
    • 类似地,因为有 \(j\) 个人不选 A,所以可以钦定 \(\color{#66CCFF}2\) 后面有 \(j-1\) 个元素,那么在这 \(j-1\) 个元素中,要选 \(n-2\) 个来放 \(\color{#66CCFF} 3 \sim n\),方案数为 \(\binom {j-1} {n-2}\)
    • 剩下的 \(i\) 个,包括 \(\color{#66CCFF}1\)\(\color{#66CCFF}2\) 之间的元素,都可以随便排列,方案数为 \((i-n)!\)
    • 同样,合法方案数即为 \(\binom {j-1} {n-2} \times (i-n)!\)

于是概率就是合法方案数除以总方案数,把 \((i-n)!\) 约掉得到:

\[f_{i,j} = \frac {\binom {j-1} {n-2}} {\binom {i-1} {n-1}} \]

B,草,原来 8e5 也能分块,应该是根号跑不满导致的,下次看到 1e6 甚至 5e6 以下的不会 log 就去想根号吧。

可以根号就简单了,这不随便做。注意到 \(fa_i < i\)\(fa\) 即 fail 数组),所以连树上分块都不用,直接对原序列分块,维护一个 \(nxt_i\) 表示从 \(i\) 往上跳祖先能跳到的第一个和 \(i\) 不在同一个块内的点,然后修改分别在跳到的所有 \(nxt\) 上打个懒标记,查询直接重构整个块把打的懒标记都跑一遍即可。

C 有点厉害了。

还是先考虑 \(k=2\)。根据上面那个结论,记 \(w_{t,i}\)\(w(i \times 2^t , (i+1) \times 2^t - 1)\),其中 \(i \in \{1,2\}\),那么有:

\[w_{t,i} = w_{t-1,i} + w_{t-1,\neg i} \]

其中 \(+\) 表示字符串拼接,\(\neg\) 表示取反。

于是,每个 \(w(l_i , r_i)\) 就可以拆成 \(O(\log V)\)\(w_{t,i}\)

回到 AC 自动机计数的过程,在对 fail 树拓扑排序之前,我们记录的是每个点被直接经过的次数。很难发现如果知道了每个 \(w_{t,i}\) 最终跑到了哪个点上,那么是可以对上面的式子倒着做,也就是倒过来的倍增,来推出自动机上每个点被经过的次数的。

考虑 dp,令 \(f_{x,t,i}\) 为从自动机上节点 \(x\) 开始,跑一遍 \(w_{t,i}\) 最终到达哪个节点,转移还是上面用那个式子倍增,有:

\[f_{x,t,i} = f_{f_{x,t-1,i},t-1,\neg i} \]

然后倒着倍增,令 \(g_{x,t,i}\) 为从节点 \(x\) 开始,跑一遍 \(w_{t,i}\) 经过的路径上的点需要被加多少次,则有转移:

\[\begin{aligned} g_{x,t,i} & \to g_{x,t-1,i} \\ g_{x,t,i} & \to g_{f_{x,t-1,i},t-1,\neg i} \end{aligned} \]

那么最后把 \(g\) 求完之后,对于所有 \(x,i\) 做一遍 \(cnt_{f_{x,0,i}} \gets g_{x,0,i}\) 即可。注意到并不需要给 \(x\) 加,因为 AC 自动机在匹配文本串的时候是从开始节点的儿子开始的。

剩下的就是板子了。

但是注意到这只是 \(k=2\),不过 \(k>2\) 的做法也比较显然了。

\(w_{t,i} = w(i \times k^t , (i+1) \times k^t - 1)\),仍然可以发现:

\[w_{t,i} = w_{t-1,i} + w_{t-1,(i+1) \bmod k} + \cdots + w_{i-1,(i+k-2) \bmod k} + w_{i-1,(i+k-1) \bmod k} \]

所以和上面的过程其实没有本质区别。

可是……可是文本串 \(S\) 是由好多个 \(w_{t,i}\) 拼起来的呀,那如果一个模式串横跨了好几个 \(w_{t,i}\) 咋办啊?这也不能暴力,然后 ta 还不给下发 std 这叫我补个毛线()

D 是神仙构造还不仅仅是神仙构造还是神仙 ds。虽然构造可爱吧但是是真的补不动。


天依宝宝可爱!

posted @ 2025-09-12 07:58  little__bug  阅读(42)  评论(0)    收藏  举报