题面:定义一个树的
value
为树的所有联通子图的节点数之和
求给出的一个树的
value
感觉很巧妙的一个 树dp
因为是一个无根树,不妨把0号节点提起来作为根,记 Tx 为以 x 为根节点的子树
定义
定义
Cx
为在
Tx
中选择
x
的联通子图的个数
考虑两个树,分别以
那么,将
先考虑简单的,
Croot
的值,如果不选
x
,那么方案数不变,如果选
对于
Sroot
的值,同样考虑是否选择
x
,如果不选择,那么对
如果选择了
x
,情况稍微复杂一点,分别考虑
对于
Tst
上的点的贡献
每一个值为
Sst
的方案都对应着
Cx
次贡献,所以对
Sroot
的贡献为
Cx×Sst
对于
Tx
上的点
同样的,每一个值为
Sx
一个方案都对应着
Cst
次贡献,所以对
Sroot
的贡献为
Cst×Sc
所以,
Sroot=Sst+Cx×Sst+Cst×Sc=(1+Cx)×Sst+Cst×Sc
#include <bits/stdc++.h>
typedef long long LL;
using namespace std;
const int mod = 1000000007;
const int maxn = 112345;
LL dp[maxn][2];
vector<int> edge[maxn];
void Link(int st,int ed){
edge[st].push_back(ed);
edge[ed].push_back(st);
}
void init(int n){
for(int i=0;i<n;i++){
edge[i].clear();
}
}
void dfs(int st,int fa){
dp[st][1] = 1;
dp[st][0] = 1;
for(auto & x:edge[st]){
if(x != fa){
dfs(x,st);
(dp[st][1] *= dp[x][0] + 1) %= mod;
(dp[st][1] += dp[st][0] * dp[x][1]) %= mod;
(dp[st][0] *= dp[x][0] + 1) %= mod;
}
}
}
class SubtreesCounting {
public:
int sumOfSizes( int n, LL a0, LL b, LL c, LL m ) {
init(n);
for(int i=1;i<n;i++){
Link(i,a0 % i);
a0 = (b * a0 + c) % m;
}
dfs(0,-1);
LL ans = 0;
for(int i=0;i<n;i++){
(ans += dp[i][1]) %= mod;
}
return (int)ans;
}
};