• 【Codeforces】 CF1097G Vladislav and a Great Legend


    题目链接

    CF方向
    Luogu方向

    题目解法

    首先一个套路是普通幂转下降幂(为什么?因为观察到 k k k 很小,下降幂可以转化组合数问题,从而 d p dp dp 求解)
    f ( X ) k = ∑ i = 0 k { k i } i ! ( f ( X ) i ) f(X)^k=\sum\limits_{i=0}^{k}{k\brace i}i!\binom{f(X)}{i} f(X)k=i=0k{ik}i!(if(X))
    现在的问题是对于所有生成树求出中间选 i i i 条边的方案数

    我们令非空顶点的点集为关键点,其他生成树上的点为包含点
    考虑树形 d p dp dp,令 f i , j f_{i,j} fi,j 表示在 i i i 的子树中选出至少 1 1 1 个关键点,且与 i i i 连通的生成树中选出 j j j 条边的方案数
    考虑转移:

    1. v v v 子树中没有关键点
      f u , i → f u , i f_{u,i}\to f_{u,i} fu,ifu,i,不能计入答案计算,因为没有改变关键点集合
    2. 只有 v v v 子树中的关键点组成
      f v , i + f v , i − 1 → f u , i f_{v,i}+f_{v,i-1}\to f_{u,i} fv,i+fv,i1fu,i,不能计入答案计算,因为这个关键点集合在 v v v 时已经计算过
    3. u , v u,v u,v 子树中均有关键点
      f u , i ∗ f v , j → f u , i + j & f u , i + j + 1 f_{u,i}*f_{v,j}\to f_{u,i+j}\&f_{u,i+j+1} fu,ifv,jfu,i+j&fu,i+j+1,可以计入答案计算,因为改变了关键点集合

    根据树形 d p dp dp 的时间复杂度计算,时间复杂度为 O ( n k ) O(nk) O(nk)

    #include 
    using namespace std;
    const int N=100100,K=210,P=1e9+7;
    int n,k,siz[N],s2[K][K],t[N],ans[N];
    int ne[N<<1],e[N<<1],h[N],idx;
    int f[N][K];
    inline int read(){
        int FF=0,RR=1;
        char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
        for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
        return FF*RR;
    }
    inline void add(int x,int y){ e[idx]=y,ne[idx]=h[x],h[x]=idx++;}
    inline void inc(int &x,int y){ x+=y;if(x>=P) x-=P;}
    void dfs(int u,int fa){
        siz[u]=1,f[u][0]=1;
        for(int i=h[u];~i;i=ne[i]){
            int v=e[i];if(v==fa) continue;
            dfs(v,u);
            for(int j=0;j<=k;j++) t[j]=f[u][j];
            for(int j=0;j<=k;j++){
                inc(t[j],f[v][j]);
                if(j) inc(t[j],f[v][j-1]);
            }
            for(int p=0,mxp=min(k,siz[u]);p<=mxp;p++) for(int q=0,mxq=min(k-p,siz[v]);q<=mxq;q++){
                int coef=1ll*f[u][p]*f[v][q]%P;
                inc(t[p+q],coef),inc(t[p+q+1],coef);
                inc(ans[p+q],coef),inc(ans[p+q+1],coef);
            }
            siz[u]+=siz[v];
            for(int j=0;j<=k;j++) f[u][j]=t[j];
        }
    }
    int main(){
        n=read(),k=read();
        s2[0][0]=1;
        for(int i=1;i<=k;i++) for(int j=1;j<=i;j++) s2[i][j]=(s2[i-1][j-1]+1ll*s2[i-1][j]*j)%P;
        memset(h,-1,sizeof(h));
        for(int i=1;i<n;i++){
            int x=read(),y=read();
            add(x,y),add(y,x);
        }
        dfs(1,-1);
        int ANS=0;
        for(int i=1,fac=1;i<=k;i++,fac=1ll*fac*i%P) ANS=(ANS+1ll*ans[i]*s2[k][i]%P*fac)%P;
        printf("%d\n",ANS);
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
  • 相关阅读:
    JTS: 15 Angle 角度计算
    GlobalWebsoket.js 的使用,实现获取实时数据
    分享一份 .NET Core 简单的自带日志系统配置,平时做一些测试或个人代码研究,用它就可以了
    HNUCM-2022年秋季学期《算法分析与设计》练习12
    计算机网络笔记5 传输层
    商业新闻|你还在用传统搜索引擎吗?
    大型商场如何设置酷客导航模式?VR全景带你了解
    电容笔哪种好?ipad第三方电容笔推荐
    OSG交互:选中场景模型并高亮显示
    QT下使用QChart绘制曲线
  • 原文地址:https://blog.csdn.net/djx2021/article/details/133841604