nfls10.1

发布时间 2023-10-01 16:47:00作者: carp_oier

T1

大水题,用位运算更加便捷求解。

T2

看出来有环了,但是没往基环树上想,寄。

暴力分,有部分分是基础树,可以跑一遍深搜,根节点的选择是 k 种颜色,剩下的是 k - 1 种颜色。还有暴力是可以二分图染色做出来的。

正解,我们对于一个环上的操作,可以用递推式子求出来。f[0][i], f[1][i] 分别表示和第一种的颜色不一样、一样。对于不一样的我们在转移的时候是 $ f[0][i] \gets f[1][i-1] * (k - 1) + f[0][i-1] * (k - 2)$,不同色的时候 \(f[1][i] \gets f[0][i-1]\)。完成了环上的递推。

一般的基环树,我们还会有很多的出边,对于出边我们可以把他们看成一棵一棵的树。我们可以用拓扑排序把这些出边给砍掉。

从本质上来说,这个题目是一个树形结构,并不是基环树dp。以后多注意这种相互依赖的关系,可能就会出现基环树的形式,然后将基环树砍开来看是不是能分解成两部分分别计算。

少生孩子多取模

T3

很像提高组之前的一个题 mayan 游戏,代码都很长很臭,让人不想写事实也确实是这样,考场上写出来但是不想调不想再看了所以给删了重新写了个小暴力。

T4

暴力分考虑
考虑出来链的情况:

首先考虑链的情况,如果它是一根链的话,每个边之间的概率都是独立的,链之间的转移就是将每一根上的概率乘起来 dp[i][j] 前 i 个点,目前长度为 j。

枚举这个边的长度,$dp[i+1][j+k] \gets dp[i+1][j+k] + dp[i][j] * 1 / p $

题目中的最长距离就是一条树的直径,因此我们考虑树的直径的形成过程,是由两个子树中最大的两个链组合而成,所以我们可以枚举一个从根节点的最长链,然后我们再考虑另外的子树中的最长的一根链。之后枚举根节点到这个链的距离,然后用之前的链的情况进行合并。

//dp[x][j]表示x这个子树前面的儿子中,最远距离为j的概率
//tmp0[k]表示x向当前儿子y最远距离为k的概率
//tmp1为新的最远距离的概率
for(int j=0;j<=L;j++)
     for(int k=0;k+j<=S;k++)
          tmp0[j+k]+=p*dp[y][k];
for(int j=0;j<=S;j++)
     for(int k=0;k+j<=S;k++)
          tmp1[max(j,k)]+=dp[x][j]*tmp0[k];
for(int j=0;j<=S;j++)dp[x][j]=tmp1[j];

但是时间复杂度会被卡掉,所以说我们还要进行优化。

我们看到中间的这两层循环,本质是在不断枚举,是当前这一棵子树中产生了最长链,还是在前面的分支中,所以说我们可以给它们用前缀和统计出来,之后减去二者相等的情况。sum[0][i] 表示在前面的分支中出现了链最长, sum[1][i] 表示在当前的这个链上的长度是最大的。