NC20811 蓝魔法师(树形dp)
计数类dp,我们设计状态为以i为根,i所在连通块大小为j的合法方案
枚举他的子树,这条边是否断裂,如果断裂,那么直接乘以子树合法方案,如果不断,那么就是计算贡献
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=1e6+10; const int mod=998244353; ll f[5050][5050]; ll sum[N]; int sz[N],n,k; int h[N],ne[N],e[N],idx; void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++; } void dfs(int u,int fa){ int i; f[u][1]=sz[u]=1; for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa) continue; dfs(j,u); ll s=0; for(int v=1;v<=min(k,sz[j]);v++){ s=(s+f[j][v])%mod; } for(int x=min(k,sz[u]);x;x--){ for(int y=min(k,sz[j]);y;y--){ if(x+y<=k){ f[u][x+y]=(f[u][x+y]+f[u][x]*f[j][y])%mod; } } f[u][x]=f[u][x]*s%mod; } sz[u]+=sz[j]; } } int main(){ ios::sync_with_stdio(false); int i,j; cin>>n>>k; memset(h,-1,sizeof h); for(i=1;i<n;i++){ int a,b; cin>>a>>b; add(a,b); add(b,a); } dfs(1,0); ll ans=0; for(i=1;i<=n;i++){ ans=(ans+f[1][i])%mod; } cout<<ans<<endl; return 0; }
没有人不辛苦,只有人不喊疼