A.首先我们注意到,条件等价于∀1≤i≤n,有prei=sufi。因为当i>n时,prei=suf2n−i,即prei=sufi和pre2n−i=suf2n−i是等价的。然后,不妨直接把条件增强,令∀1≤i≤n,均有prei<sufi,不难看出,将1至n填入前半部分,n+1至2n填入后半部分即可,顺序任意。
然后考虑Pa=b的限制,如果有a≤n和b≤n同时满足(或者同时不满足),上面的构造已经符合要求。如果两者一个满足一个不满足,则将n+1至2n填入前半部分,1至n填入后半部分即可。
不断随机几个满足Pa=b的排列,并检查是否符合条件也是可以通过的。
B.将字符0视为106,字符1视为106+1,字符2视为−(2⋅106+1)。则一个子串含有相同数量的0,1,2,当且仅当子串和为0。跑一个前缀和+map检查即可。
C.在下文中,对于路径S,我们约定用∣S∣表示路径的长度。
假设我们枚举最终的路径S=(u,v)(∣S∣>1),考虑如何计算至多有多少条不同的路径的交为该路径。其答案是sizu×sizv,其中sizu代表以对方(点v)为根时,u的子树大小。如果统一令1号点为根,则当u是v的祖先的时候,答案是(n−sizu+1)×sizv,否则是sizu×sizv。
此时可以考虑dsu on the tree。对于每个点u,维护集合{(d,sd)},代表u的子树中,深度大于等于d的点中,子树大小的最大值sd。则当合并两个集合时,子树大小为sd的节点,至少需要匹配一个子树大小为⌈sdk⌉的节点。这一步可以通过在另一个集合中lower_bound来实现。而更新对应的(d,sd)只需要对后缀取max即可。
特殊判断祖先-子孙节点的情况,和答案等于1的情况。
D.首先可以对每个连通块单独处理。假设一个连通块具有n个点,m条边。若n≤20,则我们可以暴力枚举哪些点被删除,然后统计答案,时间复杂度O(2n×m)
若n>20,则必有m−n≤20。我们找出一棵生成树,并先考虑没有非树边的情况应该怎么计算。一个简单的办法是令fi,0/1代表i的子树,点i删或者不删的最小代价,直接dp即可。而对于每条非树边,其有三种可能性:用a的代价直接删掉,被其中一个端点删掉,被另一个端点删掉。假设我们枚举这三种可能性的一种,相当于钦定了某若干个点必须删掉,仍可以套用上述的树dp。时间复杂度O(3m−n×n),显然是过不了的。
现在我们假设,对于每条边,强制枚举它被某一个端点删掉,这样复杂度就可以退化到O(2m−n×n)。但是这样子会遗漏被直接使用a的代价删掉的情况,怎么办呢?我们可以弱化对点的限制:本来情况下,枚举每条边被哪个点删掉,那个点被要求无法保留,而现在我们增加一个决策:可以保留这个点,但是需要额外支付a的代价(相当于删去这条边,放弃对强制删除点的限制)。仍可以套用上述树dp,复杂度为O(2m−n×n)。
赛时有选手写了类似于O(2n/2)的的独立集做法,没有特别看懂,应该也是对的。
退火是过不了的,不知道有没有其他技巧高超的乱搞可以过。(赛时大家都是怎么过的呢)
E.一眼:妈妈我会容斥!考虑假定选取的点具有顺序,并枚举所有的可重联通块。不妨令集合Si,j代表,第i号点和第j号点直接相邻的方案数,则对所有2k(k−1)个集合容斥即可得到答案。具体地,令fi,j表示i个点,违反j条限制(每条限制形如上述的(i,j)相邻)的方案数。对每个形状的连通快插头dp,算出恰有x条边的连通子图的方案数,然后大力dp转移……
上面这个做法不仅难写而且时间还大。但是它启发我们一件事情:假设一个连通块长为dx,宽为dy,则它在图中出现的方案数为(n−dx)(m−dy)。换句话说,纵使我们不清楚它具体的容斥系数,我们也能推断出,当n,m≥k的时候,答案是关于n,m的,不超过k次的二元多项式(只有当n,m≥k时,所有的连通块贡献才均不为0)。当n,m≤k时,答案是关于m的多项式,其中对于每个n均有不同的多项式。
接下来只需要计算出所有n,m≤2k的值,便可以插值多项式了。一种做法是轮廓线dp,注意到轮廓线上的点,至多只有一对连续的1,故每条长为n的轮廓线状态数是O(ϕn)级别的,共有n2个轮廓线要考虑。故令Fi,j,k,S代表在点(i,j)处,选了k个点,轮廓线状态为S的方案数。单个n复杂度是O(n2kϕn),总的复杂度是O(k3ϕ2k)。
赛时有一票子选手打表多项式,我应该手动输入模数p的(悲
F.本来发现了插值做法之后想加强成算Sk(k≤1000),后来因为种种原因就没有加……谢罪.jpg。
这里直接介绍原做法:令Fi,k,p表示i个变量,每个变量从1取到m,答案不超过p的方案数。我们递归地证明,Fi,k,p是关于k,p的,总次数不超过i的二维多项式(k<p≤2k)。
考虑枚举最左边的最大值位置x,令其值为k1,则若2k1≤p,方案数为k1i,若2k1>p则方案数为Fx−2,k1−1,p×Fi−x−1,k1,p×(k−k1)2。式子的含义是,最大值两端的值必须取≤k−k1的值,并且取完之后对剩下部分没有影响。(当x≤2或x≥i−1)时式子会有所区别,不再赘述。
故对于这个x,有Fi,k,p=(⌊2p⌋)i+∑k1=⌊2p⌋+1kFx−2,k1−1,p×Fi−x−1,k1,p×(k−k1)2
如果把Fi,k,p写成∑ai,jkipj的形式,可以发现我们需要的仅仅是卷积后求一次若干次幂前缀和,这是完全可以预处理的部分。
但是有另一个问题,2p是没法写进多项式里的(这个21不能简单地作为系数)。解决方案是分p=2x+1和p=2x讨论,分别建立两部分的多项式。细节会有点多。得到了最终的多项式,可以轻松求得期望。
一个事实是最终对p求和会让答案退化成关于m的一元多项式,于是可以暴力插值。如果题意改为询问Sk的值,答案会进化成n+k次多项式,就无法暴力dp求得点值了。