题意
给定一个串 s s s,求有多少长度为 m m m的串,无限循环后有一个长为 ∣ s ∣ |s| ∣s∣的子串,其字典序小于 ∣ s ∣ |s| ∣s∣。
数据范围
∣ s ∣ , m ≤ 2000 |s|,m\leq 2000 ∣s∣,m≤2000
解法
本人比较蠢没有想到补集转化,考虑直接做。
既然存在子串小于
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=1−xl1
并把这些乘起来,就是每个长度
≤
s
\leq s
≤s的串个数
现在考虑倍增得到答案,现在已经计算出了
l
∈
[
0
,
n
−
1
]
l\in [0,n-1]
l∈[0,n−1]的答案了。
如果能够计算出这部分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,2n−1]的串的多项式乘积
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,n−1]这部分乘积可以用一个套路,就是考虑乘
1
−
x
l
1-x^l
1−xl,把这个取
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(1−xl)=−∑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。
代码
要不就不贴了,又臭又长。。。