JZOJ 3844. 统计损失(count)
题目
分析
- 树形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 }
为何要逼自己长大,去闯不该闯的荒唐