zoukankan      html  css  js  c++  java
  • [CF735E/736C]Ostap and Tree

    题目大意:
      一个$n(nle100)$个点的树,将一些点染成黑点,求满足每个点到最近黑点的距离$le k(klemin(20,n-1))$的方案数。

    思路:
      树形DP。
      用$f[i][j]$表示$i$的子树中离$i$最近黑点的距离为$j$,且距离超过$j$的点都被满足的方案数。转移时新建一个临时数组$tmp$保存转移后的$f[x]$。设$y$是$x$的子结点,枚举$f[x][i]$和$f[y][j]$,转移如下:
        1.若$i+jle2k$,则此时$min(i,j+1)le k$,对于长度为$i+j+1$的链上的所有点都可以找到一边距离$le k$,因此状态合并以后是合法状态,转移$tmp[min(i,j+1)]+=f[x][i] imes f[y][j]$;
        2.若$i+j>2k$,则此时$max(i,j+1)>k$,链上肯定会存在一些点两边都够不到,转移$tmp[max(i,j+1)]+=f[x][i] imes f[y][j]$。
      初始状态$f[x][0]=1$,表示不考虑子树内的情况,选择自己的方案数为$1$;$f[x][k+1]=1$,表示自己本身不满足,但子结点都被满足的情况,主要是方便转移。
      答案为$sum_{i<=k}f[root][i]$。
      时间复杂度$O(nk^2)$。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<algorithm>
     4 #include<forward_list>
     5 typedef long long int64;
     6 inline int getint() {
     7     register char ch;
     8     while(!isdigit(ch=getchar()));
     9     register int x=ch^'0';
    10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    11     return x;
    12 }
    13 const int N=101,K=41,mod=1e9+7;
    14 int k,f[N][K],tmp[K];
    15 std::forward_list<int> e[N];
    16 inline void add_edge(const int &u,const int &v) {
    17     e[u].push_front(v);
    18     e[v].push_front(u);
    19 }
    20 void dfs(const int &x,const int &par) {
    21     f[x][0]=f[x][k+1]=1;
    22     for(int &y:e[x]) {
    23         if(y==par) continue;
    24         dfs(y,x);
    25         std::fill(&tmp[0],&tmp[k*2]+1,0);
    26         for(register int i=0;i<=k*2;i++) {
    27             for(register int j=0;j<=k*2;j++) {
    28                 (tmp[i+j<=k*2?std::min(i,j+1):std::max(i,j+1)]+=(int64)f[x][i]*f[y][j]%mod)%=mod;
    29             }
    30         }
    31         std::copy(&tmp[0],&tmp[k*2]+1,f[x]);
    32     }
    33 }
    34 int main() {
    35     const int n=getint();k=getint();
    36     for(register int i=1;i<n;i++) {
    37         add_edge(getint(),getint());
    38     }
    39     dfs(1,0);
    40     int ans=0;
    41     for(register int i=0;i<=k;i++) {
    42         (ans+=f[1][i])%=mod;
    43     }
    44     printf("%d
    ",ans);
    45     return 0;
    46 }
  • 相关阅读:
    innerHTML和innerText的使用和区别
    HTML5的快捷方式
    JSP相关知识
    <<,>>(有符号位移)和>>>(无符号位移)的使用方法,及差别
    JDK环境变量配置
    在table中加入<hr />标签为什么横线会跑到上边?
    有关List、Set、Map的基础了解
    菜鸟级-正则表达式
    Git常用的基本操作
    Mysql基本操作
  • 原文地址:https://www.cnblogs.com/skylee03/p/8989401.html
Copyright © 2011-2022 走看看