sol
设状态 \(dp_{i,j}\) 表示考虑到节点 \(i\),包括了 \(i\) 这个节点的连通块的权值和(只考虑子树内的)余数为 \(j\) 的方案数。
下文所说的“连通块的和”指连通块内的权值和对 \(3\) 取模后的值。
转移如下:
void dfs(int x,int fa){
dp[x][a[x]%3]=1;
for(int i:e[x])
if(i!=fa){
dfs(i)
int dpx0=dp[x][0];
int dpx1=dp[x][1];
int dpx2=dp[x][2];
//用 dp[x][0] 举例,dp[i][0]*dpx0 表示某一个子节点所在的连通块和为 0,然后和包含了 x 的连通块拼起来的方案数,即不断这条边的方案数。dp[i][1]*dpx0 表示断掉这条边。
dp[x][0]=dp[i][0]*dpx0+dp[i][1]*dpx2+dp[i][2]*dpx1+dp[i][1]*dpx0;
dp[x][1]=dp[i][0]*dpx1+dp[i][1]*dpx0+dp[i][2]*dpx2+dp[i][1]*dpx1;
dp[x][2]=dp[i][0]*dpx2+dp[i][1]*dpx1+dp[i][2]*dpx0+dp[i][1]*dpx2;
}
}

浙公网安备 33010602011771号