[HDU4625] JZPTREE+[国家集训队] Crash 的文明世界 题解

老师发福利,放了两道一毛一样的题。


考虑无视战术,直接化简:

\[\sum_{v=1}^ndis(u,v)^k=\sum_{v=1}^n\sum_{i=0}^k\begin{Bmatrix}k\\i\end{Bmatrix}dis(u,v)^{\underline i} \]

\[=\sum_{i=0}^k\begin{Bmatrix}k\\i\end{Bmatrix}\sum_{v=1}^ndis(u,v)^{\underline i} \]

\[=\sum_{i=0}^k\begin{Bmatrix}k\\i\end{Bmatrix}\sum_{v=1}^ni!\binom{dis(u,v)}i \]

\[=\sum_{i=0}^k\begin{Bmatrix}k\\i\end{Bmatrix}i!\sum_{v=1}^n\binom{dis(u,v)}i \]

\[=\sum_{i=0}^k\begin{Bmatrix}k\\i\end{Bmatrix}i!\sum_{v=1}^n\binom{dis(u,v)-1}i+\binom{dis(u,v)-1}{i-1} \]

为什么要进行最后一步分解呢?这和接下来的推导有关系。

实际上推到这里已经不用再推了,我们只需要能求出 \(f_{u,i}=\sum\limits_{v=1}^n\binom{dis(u,v)}i\) 就可以了。考虑换根 \(dp\)

首先显然有:

\[f_{u,0}=1+\sum_{v\in son(u)}f_{v,0} \]

对于 \(i>0\) 的情况,我们可以使用最后一步的推导。考虑最后一步 \(dis(u,v)-1\) 相当于是把问题转化到了儿子上,即:

\[f_{u,i}=\sum_{v\in son(u)}f_{v,i-1}+f_{v,i} \]

换根 \(dp\),时间复杂度 \(O(nk)\)

#include<bits/stdc++.h>
using namespace std;
const int N=155,M=50005,p=10007;
int str[N][N],f[M][N],g[M][N],ans;
vector<int>ve[M];int n,k,l,nw,aa,bb,q;
void dfs1(int x,int fa){
    for(auto y:ve[x]){
        if(y==fa) continue;dfs1(y,x);
        f[x][0]=(f[x][0]+f[y][0])%p;
        for(int i=1;i<=k;i++)
            f[x][i]=(f[x][i]+f[y][i]+f[y][i-1])%p;
    }f[x][0]++;
}void dfs2(int x,int fa){
    if(x!=1){
        for(int i=1;i<=k;i++){
            g[x][i]+=g[fa][i]+g[fa][i-1]+f[fa][i];
            g[x][i]+=f[fa][i-1]-f[x][i]-2*f[x][i-1];
            if(i>1) g[x][i]-=f[x][i-2];g[x][i]%=p;
        }g[x][0]=(g[fa][0]+f[fa][0]-f[x][0]+p)%p;
    }for(auto y:ve[x])
        if(y!=fa) dfs2(y,x);
}int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n>>k>>l>>nw>>aa>>bb>>q,str[0][0]=1;
    for(int i=1;i<n;i++){
        nw=(nw*aa+bb)%q;
        int tmp=(i<l?i:l);
        int x=i-nw%tmp,y=i+1;
        ve[x].push_back(y);
        ve[y].push_back(x);
    }for(int i=1;i<=k;i++) for(int j=1;j<=i;j++)
        str[i][j]=(str[i-1][j-1]+str[i-1][j]*j)%p;
    dfs1(1,0),dfs2(1,0);
    for(int j=1;j<=n;j++,ans=0){
        for(int i=0,jc=1;i<=k;i++,jc=jc*i%p){
            int now=str[k][i]*jc%p;
            ans=(ans+now*(f[j][i]+g[j][i]))%p;
        }cout<<(ans+p)%p<<"\n";
    }return 0;
}
posted @ 2025-01-23 09:03  长安一片月_22  阅读(11)  评论(0)    收藏  举报