首先先来画一下这个柿子
as(i)=sigema(1~n)j dis(i,j)^k
=sigema(1^n)j sigema(1~k)d S(k,d)*d!*C(dis(i,j),d)
=sigema(1~k)d S(k,d)*d! *sigema(1^n)j C(dis(i,j),d)
需要用脑子的就是sigema(1^n)j C(dis(i,j),d)了
设f[x][d]表示在x的子树内所有点到x的贡献
考虑从x的一个孩子y转移到x,所有的dis都加了1
有C(dis(x,j),d)=C(dis(y,j)+1,d)=C(dis(y,j),d)+C(dis(y,j),d-1)
所以f[x][d]+=f[y][d]+f[y][d-1]
然后二次扫描+换根即可
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; const int _=100; const int maxn=5*1e4+_; const int maxp=2*1e2+_; const int mod=1e4+7; int S[maxp][maxp],C[maxp][maxp],fac[maxp]; void yu() { fac[0]=1; for(int i=1;i<maxp;i++)fac[i]=fac[i-1]*i%mod; S[0][0]=C[0][0]=1; for(int i=1;i<maxp;i++) { C[i][0]=1; for(int j=1;j<maxp;j++) S[i][j]=(S[i-1][j-1]+j*S[i-1][j])%mod, C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod; } } int n,p; struct node { int x,y,next; }a[maxn*2];int len,last[maxn]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } int f[maxn][maxp]; void dfs(int x,int fr) { f[x][0]=1; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(y!=fr) { dfs(y,x); f[x][0]+=f[y][0]; for(int i=1;i<=p;i++) f[x][i]=(f[x][i]+f[y][i]+f[y][i-1])%mod; } } } int as[maxn]; void changert(int x,int fr) { for(int i=1;i<=p;i++) as[x]=(as[x]+S[p][i]*fac[i]%mod*f[x][i])%mod; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(y!=fr) { f[x][0]-=f[y][0]; for(int i=1;i<=p;i++) f[x][i]=((f[x][i]-f[y][i]-f[y][i-1])%mod+mod)%mod; f[y][0]+=f[x][0]; for(int i=1;i<=p;i++) f[y][i]=(f[y][i]+f[x][i]+f[x][i-1])%mod; changert(y,x); f[y][0]-=f[x][0]; for(int i=1;i<=p;i++) f[y][i]=((f[y][i]-f[x][i]-f[x][i-1])%mod+mod)%mod; f[x][0]+=f[y][0]; for(int i=1;i<=p;i++) f[x][i]=(f[x][i]+f[y][i]+f[y][i-1])%mod; } } } int main() { int L,now,A,B,C; int x,y; scanf("%d%d",&n,&p); len=1; scanf("%d%d%d%d%d",&L,&now,&A,&B,&C); for(int i=1;i<n;i++) { //scanf("%d%d",&x,&y); now=(now*A+B)%C; x=i-now%(i<L?i:L),y=i+1; ins(x,y);ins(y,x); } yu(); dfs(1,0); changert(1,0); for(int i=1;i<=n;i++)printf("%d ",as[i]); return 0; }