题目
分析
- 树形DP
- 设f[x]为他的子树的所有路径乘积的和
- 那么显然f[x]=f[v]*a[x]
- 然后统计答案的话
- 我们还需要加上一个他的每个子节点两两相乘*a[i]
- 因为子树也存在路径
- 再加本身节点值f[x],a[x];
代码
1 #include <cmath>
2 #include <cstdio>
3 #include <cstring>
4 #include <iostream>
5 #include <algorithm>
6 #define ll long long
7 const int mod=10086;
8 using namespace std;
9 struct sb
10 {
11 int to,nx;
12 }g[400001];
13 int list[400001],cnt;
14 void add(int x,int y)
15 {
16 g[++cnt].to=y; g[cnt].nx=list[x]; list[x]=cnt;
17 g[++cnt].to=x; g[cnt].nx=list[y]; list[y]=cnt;
18 }
19 ll f[100001],a[100001],h[100001];
20 ll ans;
21 void dfs(int x,int fa)
22 {
23 f[x]=a[x];
24 for (int i=list[x];i;i=g[i].nx)
25 {
26 int y=g[i].to;
27 if (y==fa) continue;
28 dfs(y,x);
29 f[x]=(f[x]+(a[x]*f[y])%mod)%mod;
30 ans=(ans+f[y]*(a[x]*h[x])%mod)%mod;
31 h[x]=(h[x]+f[y])%mod;
32 }
33 ans=(ans+f[x])%mod;
34 }
35 int main()
36 {
37 int n;
38 scanf("%d",&n);
39 for (int i=1;i<=n;i++)
40 scanf("%d",&a[i]);
41 for (int i=1,x,y;i<=n-1;i++)
42 {
43 scanf("%d%d",&x,&y);
44 add(x,y);
45 }
46 dfs(1,-1);
47 cout<<ans;
48 return 0;
49 }