一般这种统计里面带k次方的都要转换成组合数把。。。
有:x^k=Σ(i=1,n) Stirling2(k,i)*P(x,i),而P(x,i)=C(x,i)*i!,这样就成功转化成组合数了。那么答案就是对于一定定点x要统计所有的Σ(i=1,n) C(dist(x,i),j) j=1...n,那么利用C(i,j)=C(i-1,j-1)+C(i-1,j),以及父亲和儿子的答案(dist刚好相差1)得到x的答案。上下dfs一遍即可。
AC代码如下:
#include<iostream> #include<cstdio> #define mod 10007 #define N 50005 #define M 155 using namespace std; int n,m,tot,L,now,A,B,Q,fst[N],pnt[N<<1],nxt[N<<1],f[N][M],g[N][M],s[M][M],fac[M]; void add(int x,int y){ pnt[++tot]=y; nxt[tot]=fst[x]; fst[x]=tot; } void ad(int &x,int y){ x+=y; if (x>=mod) x-=mod; } void dl(int &x,int y){ x-=y; if (x<0) x+=mod; } void dfs1(int x,int fa){ int p,i; f[x][0]=1; for (p=fst[x]; p; p=nxt[p]){ int y=pnt[p]; if (y!=fa){ dfs1(y,x); ad(f[x][0],f[y][0]); for (i=1; i<=m; i++) ad(f[x][i],(f[y][i]+f[y][i-1])%mod); } } } void dfs2(int x,int fa){ int p,i; if (fa){ g[x][0]=n-f[x][0]; for (i=1; i<=m; i++){ ad(g[x][i],((g[fa][i]+g[fa][i-1]+f[fa][i]+f[fa][i-1]-f[x][i]-(f[x][i-1]<<1))%mod+mod)%mod); if (i>1) dl(g[x][i],f[x][i-2]); } } for (p=fst[x]; p; p=nxt[p]) if (pnt[p]!=fa) dfs2(pnt[p],x); } int main(){ scanf("%d%d%d%d%d%d%d",&n,&m,&L,&now,&A,&B,&Q); int i,j,x,y,tmp; for(i=1; i<n; i++){ now=(now*A+B)%Q; tmp=min(i,L); x=i-now%tmp; y=i+1; add(x,y); add(y,x); } s[0][0]=1; for (i=1; i<=m; i++) for (j=1; j<=i; j++) s[i][j]=(s[i-1][j]*j+s[i-1][j-1])%mod; fac[1]=1; for (i=2; i<=m; i++) fac[i]=fac[i-1]*i%mod; dfs1(1,0); dfs2(1,0); for (i=1; i<=n; i++){ x=0; for (j=1; j<=m; j++) ad(x,s[m][j]*fac[j]%mod*(f[i][j]+g[i][j])%mod); printf("%d\n",x); } return 0; }
by lych
2016.4.23