luogu5404 CTS2019 重复

题意

给定一个串 s s s,求有多少长度为 m m m的串,无限循环后有一个长为 ∣ s ∣ |s| s的子串,其字典序小于 ∣ s ∣ |s| s

数据范围

∣ s ∣ , m ≤ 2000 |s|,m\leq 2000 s,m2000

解法

本人比较蠢没有想到补集转化,考虑直接做。

既然存在子串小于 s s s,那么考虑找到整个串中字典序最小的长为 s s s的子串。
这个串是循环的,所以其实就是找长为 m m m的串的最小表示法。
设长为 m m m的串为 t [ 1   . . .   m ] t[1\ ...\ m] t[1 ... m],有下面这个经典结论
如果 t t t没有循环节,那么 t t t的最小表示一定是一个lyndon串
有循环节的情况就把 m m m变成了 m m m的约数,那不妨先考虑对于一个 m m m怎么做

问题变成这样,求字典序小于 s s s的长为 m m m的lyndon串数量。
可以发现将 s s slyndon分解后,只留存第一段,答案仍然是不变的。
原因是如果 t t t s s s在第一段能比出大小就不需要说了,如果比不出来说明第一段 s 0 s_0 s0 t t t的前缀,那么 t t t的后面所有长为 ∣ s 0 ∣ |s_0| s0的子串都 ≥ s 0 \geq s_0 s0,而 s s s的后面的分解都比 s 0 s_0 s0小,一个一个拿出来比较不会有 t < s t<s t<s的结果,所以肯定不行。
因此可以先对 s s slyndon分解,只留存第一段。

这样 s s s也是一个lyndon串了。
现在考虑计数的问题,可以想到一个非lyndon串会有自己的lyndon分解,而且每一部分都是递减的
先考虑递推,长度为 l l l的非lyndon串一定是一些长度小于 l l l的lyndon串拼成的,而且可以发现只要所有串都 ≤ s \leq s s,那么整个串就 ≤ s \leq s s了。
这个对于 < < <是不成立的,所以把限制换成 ≤ s \leq s s会更好做一些。
而每次求非lyndon串的时候就是计数可重集,容易得到 O ( m 2 ) O(m^2) O(m2)的做法

其实是可以继续优化的,如果把长为 l l l的lyndon串看成多项式:
∑ i = 0 x i l = 1 1 − x l \sum_{i=0} x^{il}=\frac{1}{1-x^l} i=0xil=1xl1
并把这些乘起来,就是每个长度 ≤ s \leq s s的串个数
现在考虑倍增得到答案,现在已经计算出了 l ∈ [ 0 , n − 1 ] l\in [0,n-1] l[0,n1]的答案了。
如果能够计算出这部分lyndon串的多项式乘积 m o d   x 2 n mod\ x^{2n} mod x2n的值,用 ≤ s \leq s s串的个数的多项式去除它,就可以得到 l ∈ [ n , 2 n − 1 ] l\in [n,2n-1] l[n,2n1]的串的多项式乘积 m o d   x 2 n mod\ x^{2n} mod x2n,又因为这些多项式次数都 ≥ n \geq n n,不会有交叉项,那么它们各项的值和lyndon串个数是吻合的。
而计算 l ∈ [ 0 , n − 1 ] l\in [0,n-1] l[0,n1]这部分乘积可以用一个套路,就是考虑乘 1 − x l 1-x^l 1xl,把这个取 l n ln ln
l n ( 1 − x l ) = − ∑ i = 0 x i l i ln(1-x^l)=-\sum_{i=0}\frac{x^{il}}{i} ln(1xl)=i=0ixil
这样直接暴力计算 l n ln ln的和,是 O ( n l o g n ) O(nlogn) O(nlogn)的,然后多项式 e x p exp exp即可。
总复杂度 T ( n ) = T ( n 2 ) + O ( n l o g n ) T(n)=T(\frac{n}{2})+O(nlogn) T(n)=T(2n)+O(nlogn),所以是 O ( n l o g n ) O(nlogn) O(nlogn)
在这里就是 O ( m l o g m ) O(mlogm) O(mlogm),而且顺路 l ∈ [ 1 , m ] l\in [1,m] l[1,m]全部算出来了,不需要对因数再做。

还有一个小细节就是 ∣ s ∣ < m |s|<m s<m的情况,需要把 s s s不断循环,这样可以保证不会多算lyndon串作为答案,也可以保证 ≤ s \leq s s的组合仍然 ≤ s \leq s s的性质。注意在 m = ∣ s ∣ m=|s| m=s时要把相等的情况减掉。

这样这道题就做完了,时间复杂度 O ( m l o g m + ∣ s ∣ ) O(mlogm+|s|) O(mlogm+s)

当然常数是巨大的,没法与神仙rqy相比了,orz rqy。

代码

要不就不贴了,又臭又长。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值