A. String Master

$O(n^3)$随便做。

 

 

 

B. Tourist Attractions

因为数据范围$n^2$没有任何问题。

考虑设$dp(i,j,k)$表示节点i从节点j来,并再走k步的方案数。

显然$dp(i,j,1)=du(i)-1$,除了返回j,别的方案都是可行的。

设$link(i,j)$表示i,j是否联通的0/1变量。

$dp(i,j,2)=\sum \limits_{k,link(i,k)}dp(k,i)-link(k,j)$,当k可以走回j的时候,可能造成重复计数,故减去。

$dp(i,3)=\sum \limits_{k,link(i,k)}dp(k,i)$

$ans=\sum \limits_{i=1}^{n}dp(i,3)$

瓶颈在于如何求$dp(i,j,2)$,暴力求是$O(n^3)$的。

不妨将式子中加和减的两项拆开,那么发现bitset维护一下i走到k再走到j的方案数就可以了。

 

 

 

C. Walk

70分暴力,每个值只在bfs第一次出现时,更新一遍它的所有子集。

枚举子集的复杂度是$O(3^k)$的。(k为val二进制下最大的位数)

问题在于如何将$3^k$的边转化为$2^k$级别。

考虑由每个权值向1的个数减少1的权值建边权为0的边,那么边的个数为$k*2^k$级别。

由点向权值建边权为0的边,权值向对应的点建权值为1的边。

因为权值只有0/1两种形式,双端队列bfs。

 

另外,如果点向权值建边权为1的边,权值向点建权值为0的边。

这样进行bfs是错误的,原因是可能导致点被提前更新更大的答案。

 

 

 

另外记录一道与本题稍有一点关系的特殊的题目(LadyLex学长的课件):

有$2^{20}$个元素,每次使某元素对给定值取$max$,求某个数代表的二进制的子集中元素的最大值。

有这样的状态定义:$F[i][j]$代表“状态s的前一半数位为i的子集,后一半数位为j”的方案数/最小值等信息。

这样在更新和查找的时候,我们都只需要枚举一半的数位(查找枚举j的子集,更新枚举i的超集),从而给状压那一块的复杂度开了个根号。