zoukankan      html  css  js  c++  java
  • 【Codeforces 949D】Shake It! 【动态规划】

    参考: http://blog.csdn.net/gjghfd/article/details/77824901

    所求的是满足条件的图中“不同构”的数量,意味着操作的顺序是可以忽略的。考虑若干次操作后得到的一个“World” G,其中某次操作(s(G), t(G))生成的节点为w,则由s(G)到w和由w到t(G)的所有路径及途径点生成的两个子图分别符合“World”的定义。

    这意味着我们可以将一个“World”分割成若干个子问题来求解。

    不妨令F(N, M)表示经N次操作后得到的s(G)与t(G)之间最小割为M的所有不同构的G的数量。考虑N次操作中所有基于u=s(G), v=t(G)的操作生成的子“world”,如图所示:

    则有$$N = sum_i (a_i + c_i + 1) \ M = sum_i min{b, d} $$

    由此可以按照a, b, c, d对这些成对的子世界分类,令$$g(i, j) = sum_{a+c+1=i land min{b, d} = j} F(a, b) * F(c, d) $$

    这样我们就可以类比背包问题的求解过程,从小到大依次求出g(i, j),并用g(i, j)更新F的答案。

    考虑当前要将t组在g(i, j)中的“子世界对”放入背包,而F(x,y)是尚未考虑将g(i, j)作为子世界的情况的世界数量,那么状态转移的过程就相当于在g(i,j)中可重复地选取t个子世界对,使得总操作数变为x+t*i,总割集变为y+t*j。由于“同构”的定义不考虑操作的顺序,上述转移的方案数应为$inom{g(i, j) + t - 1}{t} $

    即状态转移为$$F(x, y) cdot inom{g(i, j) + t - 1}{t} Longrightarrow F(x+t*i, y+t*j)$$

    代码实现如下

     1 By Asm.Def, contest: Codeforces Round #431 (Div. 1), problem: (D) Shake It!, Accepted, #
     2 
     3 #include <bits/stdc++.h>
     4 using namespace std;
     5 const int maxn = 52, mod = 1000000007;
     6 typedef long long LL;
     7 int N, M, F[maxn][maxn], G[maxn][maxn], inv[maxn];
     8 
     9 void init()
    10 {
    11     scanf("%d%d", &N, &M);
    12     inv[1] = 1;
    13     for(int i = 2;i < maxn;++i)
    14         inv[i] = LL(mod-mod/i) * inv[mod%i] % mod;
    15 }
    16 void work()
    17 {
    18     F[0][1] = 1;
    19     for(int i = 1;i <= N;++i) for(int j = 1;j < maxn;++j)
    20     {
    21         for(int a = 0;a < i;++a)
    22         {
    23             G[i][j] = (G[i][j] + (LL) F[a][j] * F[i-1-a][j]) % mod;
    24             for(int b = j+1;b <= i+1 && b < maxn;++b)
    25             {
    26                 G[i][j] = (G[i][j] + (LL) F[a][b] * F[i-1-a][j]) % mod;
    27                 G[i][j] = (G[i][j] + (LL) F[a][j] * F[i-1-a][b]) % mod;
    28             }
    29         }
    30         //get G[i][j]
    31         for(int x = N-1;x >= 0;--x) for(int y = 1;y < maxn;++y) if(F[x][y])
    32         {
    33             int C = 1;
    34             for(int t = 1;x+t*i <= N && y+t*j < maxn;++t)
    35             {
    36                 C = (LL) C * (G[i][j]-1+t) % mod * inv[t] % mod;
    37                 F[x+t*i][y+t*j] = (F[x+t*i][y+t*j] + (LL) F[x][y] * C) % mod;
    38             }
    39         }
    40     }
    41     printf("%d
    ", F[N][M]);
    42 }
    43 int main()
    44 {
    45     init();
    46     work();
    47     return 0;
    48 }
    动态规划
  • 相关阅读:
    SQL里的EXISTS与in、not exists与not in
    N秒后自动跳转
    Array类型的扩展
    css中block与inline的区别
    数据绑定表达式语法(Eval,Bind区别)
    case
    SCOPE_IDENTITY、IDENT_CURRENT 和 @@IDENTITY的比较 (转载)
    内容随鼠标漂移
    IIS下下伪静态html(URL Rewrite)设置方法
    sql查询含有某列名的所有表
  • 原文地址:https://www.cnblogs.com/Asm-Definer/p/7583865.html
Copyright © 2011-2022 走看看