NOIP 模拟 15
A 选取字符串
考虑只有一个 \(p\) 的情况,肯定是统计每个的贡献,设 \(num_i\) 表示前缀长度为 \(i\) 时能匹配的串的数量,这个直接递推求就行了,然后再加上一个 \(q\),那每次只统计新的前缀的贡献,设 \(f_i\) 表示长度为 \(i\) 的前缀中有多少个前缀也合法,计算就是 \((2f_i-1) {{num_i}\choose {k}}\),减一是因为 \(p=i,q=i\) 算重了。
B 取石子
先考虑一堆石子,奇数时必胜,然后如果是偶数,如果除以 \(2\) 的商还是奇数,那就拿 \(2\),以此类推,拿 \(4,8,16\),直到除以这个 \(2^k\) 的商为奇数就先手必胜,所以每个数都可以转化成 \(\frac{x}{2^k}\) 的形式,所以当所有数的异或和为零或者 \(\text{lowbit}>k\) 时,先手必败。
然后考虑将后手置于必败情况,肯定先拿这个 lowbit
,这样因为后手的限制一定不可能拿到新的 lowbit
,所以先手就不断地拿 lowbit
就可以必胜。
C 均衡区间
单调栈处理出来控制区间后就是二维数点板子。
D 禁止套娃
首先二进制枚举外层,内层 DP 可以做到 \(\mathcal{O}(2^nn)\),拿到 30pts。发现这是一个区分内外层的 DP,考虑使内层外层都能不重不漏地统计到所有本质不同子序列,只统计第一次出现的位置,需要满足一下限制,设内外层选取的相邻两个数为 \(x,y\),则 \(x,y\) 直接没有等于 \(y\) 的数,设 \(g_{i,j}\) 表示在 \([i+1,j-1]\) 选取外层的方案数,\(f_i\) 表示内外层最后选的位置为 \(i\) 的方案数,转移形如 \(f_i=\sum_{j=0}^{i-1}g_{j,i}f_j\),钦定 \(n+1\) 位置必选后,\(f_{n+1}\) 即为答案。
考虑对于 \(f_i\) 的转移需要满足的限制。
- 对于外层 \(g\),还是相邻之间不能相同。
- 对于外层 \(g\) 选取的最后一个数,它与 \(i\) 之间没有等于 \(a_i\) 的数。
- 对于外层 \(g\) 选取的所有数中,不能有等于 \(a_i\) 的数。
发现对于第二条限制比较麻烦,所以只考虑处理满足两个限制的 \(g\),转移时减去不合法的即可,就是 \(f_i=\sum_{j=0}^{i-1}(g_{j,i}-g_{j,pre_i})f_j\)。
现在来详细揭秘一下如何处理 \(g\),结合代码比较好理解。
for(int i=1;i<=n+1;++i){
int s=1;
for(int j=i-1;~j;--j)
g[i][j]=s,vis[j]=a[j]==a[i]?0:s,s=(1ll*s-vis[next[j]]+vis[j])%mod;
}
这里的 \(g_{i,j}\) 中 \(i\) 是右端点,\(j\) 是左端点,只能这样向回递推来处理,确保了转移顺序是一个个推过去的,然后就是和 30pts 暴力的转移一样,需要使用前缀和优化,\(vis_j\) 表示 \([j,i]\) 这一段的方案数,当 \(a_i=a_j\) 时,不能从这一段转移,所以要赋 \(0\),\(s\) 更新时当前位置回替代 next
位置,所以要减去。
总结
这场发挥算正常,酒店清醒的,然后 T1 暴力跳的 fail
太唐了,T2 想到跳 \(2\) 没往下推,就会暴力太菜了。