Codeforces Global Round 7 题解

A

一种合法构造方式是(299cdots 9)

code

B

发现每次的(x_{i-1})都是知道的,于是可以直接递推。

code

C

最终答案所选的数一定是(n-k+1)(n)的所有数。把这些数所在的位置记作(p_1,p_2,cdots,p_k). 不难发现每个(r_iin [p_i,p_{i+1})),于是答案就是(prod (p_{i+1}-p_i)).

code

D

首先把首尾能构成回文的部分删掉,因为这部分一定会出现在答案中。

问题变成了在当前字符串中选取一个前缀/后缀,使其为回文串且长度尽可能长。这个可以使用manacher/hash/回文自动机实现。这里笔者使用的是双hash(欢迎来hack)

code

E

注意到答案是单调不升的,我们可以从大到小扫一遍并判断当前答案是否成立。

考虑对于一个数(x)它何时不能成为答案:对于从右往左数的第(i)个比(x)大或相等的数,其右边至少有(i)个炸弹。

我们考虑维护(b_i)为位置(i)右边大于(b_i)的大于等于当前答案的数减去(i)右边炸弹的数量。当(max(b_i)leq 0)时说明当前的答案过大。

(b_i)的维护可以使用线段树。

code

F

(f_s)是构成串(s)的方案数。直接(f_s)求显然过于复杂,我们考虑容斥的想法,令(F_s)表示构成串(s)的数量,其中(s_i=1)表示(p_i)(p_{i+1})相互认识,(s_i=0)表示不限制(p_i)(p_{i+1})的关系。不难发现有(F_s=sum_{ssubseteq t}f_t).这样我们可以求出(F),之后直接用FWT求出(f).

这样转化之后有一个重要的性质:我们可以忽略原串的位置限制,而是将(n)个人划分成若干个等价类(p(1),p(2),cdots,p(k)).每个等价类中的所有人需要连成一条链,等价类之间的边会随着当前的串(s)而唯一确定。举一个例子:(F_{1100111}=F_{0111011}).这个性质的重要之处在于大大压缩了有效状态数,有效状态数为(n)的划分数,大致在几百左右。

先考虑一个简单的问题:如何对单个等价类求答案。我们记(G_s)表示将集合(s)中的人连成一条链的方案数,这个的转移比较简单,记(g_{s,i})为集合(s)中的人连成一条以(i)结尾的链的方案数,对(g)暴力转移之后有(G_s=sum_{iin s}g_{s,i}).

接下来考虑如何通过(G)(F)(注意此时(F)的下标对应着(n)的每一种划分方案).可以把答案写成这样

[sum_{sum_{i=1}^k |p(i)|=n forall i,j p(i)igcap p(j)=empty }prod_{i=1}^k G_{p(i)} ]

枚举(n)的每一种划分方案,将条件2转化为(igcup p(i)={1,2,cdots,n}),这样的话可以直接对(G)做一遍(or)的FWT来求出(F_i).在实现上,可以将原来的(G_s)变形为(G_{|s|,s}),然后在枚举划分的时候将对应的(G_{i,s})算上即可。

最后枚举(s),根据FWT的结果求出(F_s),再求出(f_s)即可。具体实现可参照程序。

code

原文地址:https://www.cnblogs.com/encodetalker/p/12602482.html