noi前第九场 题解

A. s1mple

可以发现 0/1 这个限制类似于求路径数,使得路径经过的边权恰好合法。
显然可以用容斥来求,这样可以将问题转化为钦定其中若干条边权为 \(1\),其他边权任意的路径数。
这样做有一个好处,原来问题中的 \(2^{n-1}\) 的集合可以缩减状态数。
对于钦定之后的若干条 \(1\) 边组成的链,可以直接视为无序的。
也就是说,可以直接对 \(n\) 进行整数划分,然后求这种整数划分的方案数,即可放到对应的集合状态上。
对于求方案数,只要首先 \(dp\) 出一个集合组成一条链的方案数。
对于每种整数划分,用类似不交并卷积的思想卷在一起即可。
注意到这里对于每种整数划分,所有项加和起来才恰好为 \(n\),所以不需要用不交并卷积的占位多项式。
注意到只需要 \(ifwt\) 单点插值,所以可以在整数划分的同时进行卷积,优化一下复杂度。
 

B. s2mple

可以发现这样一个事情:
原问题等价于对于 \(s[l,r]\) 的两边添加字符,能形成的满足前面或者后面添加的字符本质不同的方案数之和。
\(SAM\) 上做这道题,考虑首先找到 \(s[l,r]\) 对应的节点,对于在前面添加字符的限制,只要对子树求和。
对于在后面添加字符的限制,其实只需要在树上用一个 \(set\) 启发式合并 \(endpos\),并用 后缀数组/另一个后缀自动机 统计本质不同的前缀个数即可。
另外一个做法是直接在 \(DAG\)\(dp\) 求出这个点出发的本质不同的路径数。
注意对于子树中的节点 \(x\) 可以直接统计 \((len_x - len_{fail_x})*dp_x\)
而对于当前节点,有一个长度限制,所以只能统计 \((len_x - (r-l+1) +1)*dp_x\)
 

C. s3mple

容易发现可以把原问题放到笛卡尔树上,然后可以随便写个 \(dp\)
然后可以发现状态里的 \(l,r\) 是没用的,所以直接记录区间长度、需要统计的贡献数。
观察贡献的式子可以猜测贡献不会很大,所以可以另外写个 \(dp\),来处理出每个区间长度的贡献上界。
可以发现这个玩意大概是 \(n log\) 级别的,在 \(n=200\) 的时候达到 \(735\)
暴力去做 \(dp\),加个取模次数优化、循环展开、卡卡上下界就可以过掉这道题了。
正解的做法是这样的,题中的 \(P\) 为一个大质数。
最终的多项式是一个不超过 \(735\) 次的多项式。
所以可以在点值意义下做多项式卷积,对于每次询问暴力插值得到系数就好了。

posted @ 2020-07-21 20:47  skyh  阅读(222)  评论(1编辑  收藏  举报