LG P4156 [WC2016]论战捆竹竿

Description

是一个美好的下午,小 W 和小 C 在竹林里切磋捆竹竿的技艺。

竹林里有无数根完全一样的短竹子,每一根竹子由 $n$ 节组成。

这些竹子比较特别,每一节都被染上了颜色。可能的颜色一共 26 种,分别用小写英文字母 a 到 z 表示。也就是说,如果把竹子的底端到顶端的颜色按顺序写出来可以排成一个由小写英文字母组成的字符串。

小 W 和小 C 都是捆竹竿的高手,他们知道怎样才能把零散的短竹子捆成一整根长竹竿。 初始时你拿着一根短竹子作为当前的竹竿。 每次你可以选择一根短竹子,短竹子底端若干节(可以是 $0$ 节)与竹竿的最上面若干节对应地一节一节捆起来,而短竹子前面剩下的节伸出去,这样就得到了一根更长的竹竿。注意,竹子的底端是靠近根部的那一端,不可以颠倒。

小 W 对竹竿的审美要求很高, 他捆竹竿时有一个癖好: 如果两根竹子的某两节被捆在了一起,那么它们的颜色必须相同。

我们假设一根短竹子从底端到顶端每节的颜色为 aba

那么两根竹子可以首尾捆在一起,可以得到一根颜色为 abaaba 的竹竿;也可以将第一根顶端的一节 a 与第二根底端的一节 a 捆在一起,得到一根颜色为ababa 的竹竿; 还可以直接将每一节都对应起来,捆成一根颜色为 aba 的竹竿。

假设我们在颜色为 ababa 的竹竿顶端再捆一根竹子,则可以捆成 ababaabaabababa 和ababa 三种不同的情况。

但是小 C 在这个问题上有不同的看法,他认为小 W 捆不出很多种长度不同的竹竿。小 W 非常不服,于是他找到了你——现在请你求出在竹竿长度不超过 ww 的情况下, 小 W 可以捆出多少种长度不同的竹竿。 其中, 竹竿的长度指从底端到顶端的竹子的节的个数。

注意:如果 $w < n$,则没有合法的长度,此时答案为$0$

Solution

一个字符串的border可以被划分成$O(logn)$个等差数列

设border集合中的某个元素为$len$,则每次可以对这个字符串增长$n-len$

所以问题转化为$\sum_{i=1}^{siz}a_il_i$在$[0,w-n]$中能取到的值的个数

所以可以用同余最短路求解

但是时间复杂度为$O(n^2)$,所以选择使用等差数列的性质优化

对于每个等差数列,在将其加入最短路时,都可以视为从首项开始,移动数个公差所得到的最短路

最终路径会形成$gcd(d,a_1)$个环,对于每个环,其中最短路最小的那个一定不会被更新,所以从该点开始更新,维护一个单调队列

还涉及到最短路数组在不同模数下的转换

设之前的模数为$mod$,现在的模数为$now$

首先有

$$g_i=min(f_j),f_j \bmod{now} =i$$

因为$f_i$表示的是$f_i+k \times mod$可以访问

所以用$f_i$更新$(f_i+mod) \bmod now$

总时间复杂度$O(nlogn)$

[WC2016]论战捆竹竿

 

posted @ 2020-10-15 12:45  QDK_Storm  阅读(83)  评论(0编辑  收藏  举报