CF1097G Vladislav and a Great Legend
Posted cjoiershiina-mashiro
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1097G Vladislav and a Great Legend相关的知识,希望对你有一定的参考价值。
Link
首先Stirling数拆一下自然数幂得到(ans=sumlimits_{i=0}^nleft{_i^k
ight}i!sumlimits_{X
evarnothing}{f(X)choose i})。
({f(X)choose i})就是在(X)的Steiner树中选(i)条边的方案数。
考虑树形dp来算这个东西,强制(X)的Steiner树的根是(X)中最浅的点。
设(f_{u,i})表示(u)的子树中的所有点集的Steiner树选(i)条边的方案数之和,考虑如何从(u)的儿子(v)转移到(u),分点集的情况以及((u,v))是否选讨论:
记(t)为合并(v)之前的(f_u)。
(1.)点集中的点都不在(v)的子树中:(forall iin[0,min(size_v,k)],f_{u,i}+=t_i)。
(2.1)点集包含(u),且除此之外的点都在(v)的子树中,((u,v))不选:(forall iin[0,min(size_v,k)],f_{u,i}+=f_{v,i})。
(2.2)点集包含(u),且除此之外的点都在(v)的子树中,((u,v))被选:(forall iin[1,min(size_v,k)],f_{u,i}+=f_{v,i-1})。
(3.1)点集横跨(u)的其它子树以及(v)的子树,((u,v))不选:(forall iin[0,min(k,size_v)],jin[0,min(k-i,size_u)],f_{u,i+j}+=t_if_{v,j})。
(3.2)点集横跨(u)的其它子树以及(v)的子树,((u,v))被选:(forall iin[0,min(k,size_v)],jin[0,min(k-i,size_u)],f_{u,i+j+1}+=t_if_{v,j})。
((3.2)中多转移的直接无视就好了)
注意实时更新(size),同时记录一下(sum_i)表示所有点集的Steiner树选(i)条边的方案数之和,最后算出答案就好了。
时间复杂度是(O(nk))的。
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstring>
const int N=100007,M=207,P=1000000007;
namespace IO
{
char ibuf[(1<<21)+1],*iS,*iT;
char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
int read(){int x=0,c=Get();while(!isdigit(c))c=Get();while(isdigit(c))x=x*10+c-48,c=Get();return x;}
}
using IO::read;
int min(int a,int b){return a<b? a:b;}
int mod(int x){return x+(x>>31&P);}
int inc(int a,int b){return mod(a+b-P);}
int dec(int a,int b){return mod(a-b);}
int mul(int a,int b){return 1ll*a*b%P;}
std::vector<int>e[N];int n,k,ans,fac[M],S[M][M],f[N][M],size[N],t[M],sum[M];
void dfs(int u,int fa)
{
size[u]=1,f[u][0]=1;
for(int v:e[u])
{
if(v==fa) continue;
dfs(v,u),memcpy(t,f[u],(k+1)<<2),f[u][0]=inc(f[u][0],f[v][0]);
for(int i=1;i<=min(k,size[v]);++i) f[u][i]=inc(f[u][i],inc(f[v][i],f[v][i-1]));
for(int i=0;i<=min(k,size[u]);++i)
for(int j=0,x;j<=min(k-i,size[v]);++j)
x=mul(t[i],f[v][j]),f[u][i+j]=inc(f[u][i+j],x),sum[i+j]=inc(sum[i+j],x),f[u][i+j+1]=inc(f[u][i+j+1],x),sum[i+j+1]=inc(sum[i+j+1],x);
size[u]+=size[v];
}
}
int main()
{
n=read(),k=read(),fac[0]=1,S[1][1]=1;
for(int i=1;i<=k;++i) fac[i]=mul(fac[i-1],i);
for(int i=2;i<=k;++i) for(int j=1;j<=k;++j) S[i][j]=inc(S[i-1][j-1],mul(S[i-1][j],j));
for(int i=1,u,v;i<n;++i) u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);
dfs(1,0);
for(int i=1;i<=k;++i) ans=inc(ans,mul(mul(fac[i],S[k][i]),sum[i]));
printf("%d",ans);
}
以上是关于CF1097G Vladislav and a Great Legend的主要内容,如果未能解决你的问题,请参考以下文章
@codeforces - 1097G@ Vladislav and a Great Legend
CF1106F Lunar New Year and a Recursive Sequence 原根矩阵快速幂高次剩余BSGS