• LOJ#3023 老C的键盘


    给定树,每条边有个大于号或者小于号,表示两个节点编号的大小关系。问有多少种树满足条件。n <= 100

    解:树形DP。

    设fij表示以i为根的子树中i是第j小的。转移的时候要乘上两个组合数。

     1 #include <bits/stdc++.h>
     2 
     3 const int N = 110, MO = 1000000007;
     4 
     5 struct Edge {
     6     int nex, v, len; /// 0  fa<son    1 fa>son
     7 }edge[N << 1]; int tp;
     8 
     9 int f[N][N], e[N], n, siz[N], temp[N], C[N][N];
    10 char str[N];
    11 
    12 inline void add(int x, int y, int z) {
    13     tp++;
    14     edge[tp].v = y;
    15     edge[tp].len = z;
    16     edge[tp].nex = e[x];
    17     e[x] = tp;
    18     return;
    19 }
    20 
    21 void DFS(int x) {
    22     siz[x] = 1;
    23     f[x][1] = 1;
    24     for(int i = e[x]; i; i = edge[i].nex) {
    25         int y = edge[i].v;
    26         //printf("%d -> %d 
    ", x, y);
    27         DFS(y);
    28         /// DP
    29         memcpy(temp, f[x], sizeof(f[x]));
    30         memset(f[x], 0, sizeof(f[x]));
    31         for(int j = 1; j <= siz[x]; j++) {
    32             /// temp[j]
    33             if(!temp[j]) continue;
    34             for(int k = 1; k <= siz[y]; k++) {
    35                 //if(y == 5) printf("len = %d 
    ", edge[i].len);
    36                 if(edge[i].len) { /// fa > son
    37                     for(int p = j + k; p <= j + siz[y]; p++) {
    38                         f[x][p] = (f[x][p] + 1ll * temp[j] * f[y][k] % MO * C[p - 1][j - 1] % MO * C[siz[x] + siz[y] - p][siz[x] - j] % MO) % MO;
    39                         //printf("f %d %d = %d 
    ", x, p, f[x][p]);
    40                     }
    41                 }
    42                 else { /// fa < son
    43                     for(int p = j; p <= j + k - 1; p++) {
    44                         f[x][p] = (f[x][p] + 1ll * temp[j] * f[y][k] % MO * C[p - 1][j - 1] % MO * C[siz[x] + siz[y] - p][siz[x] - j] % MO) % MO;
    45                         //printf("f %d %d = %d 
    ", x, p, f[x][p]);
    46                     }
    47                 }
    48             }
    49         }
    50         siz[x] += siz[y];
    51     }
    52     return;
    53 }
    54 
    55 int main() {
    56     scanf("%d", &n);
    57     for(int i = 0; i <= n; i++) {
    58         C[i][0] = C[i][i] = 1;
    59         for(int j = 1; j < i; j++) {
    60             C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MO;
    61         }
    62     }
    63     scanf("%s", str);
    64     for(int i = 2; i <= n; i++) {
    65         if(str[i - 2] == '<') {
    66             add(i / 2, i, 0);
    67         }
    68         else {
    69             add(i / 2, i, 1);
    70         }
    71     }
    72 
    73     DFS(1);
    74 
    75     int ans = 0;
    76     for(int i = 1; i <= n; i++) {
    77         ans = (ans + f[1][i]) % MO;
    78     }
    79     printf("%d
    ", ans);
    80     return 0;
    81 }
    AC代码
  • 相关阅读:
    DM7 安装
    LeetCode 第 183 场周赛
    MySQL 源码中的 ut_a 、 ut_ad
    存储领域的会议和研究机构
    LeetCode 第 15 场双周赛
    LeetCode 第 167 场周赛
    值得推荐的C/C++框架和库
    InnoDB 中的锁实现
    LeetCode-第 166 场周赛
    LeetCode 第 165 场周赛
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10516526.html
Copyright © 2020-2023  润新知