【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。由于“同构”的定义不考虑操作的顺序,上述转移的方案数应为$\binom{g(i, j) + t - 1}{t} $

即状态转移为$$F(x, y) \cdot \binom{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\n", F[N][M]);
42 }
43 int main()
44 {
45     init();
46     work();
47     return 0;
48 }

动态规划

时间: 2024-10-06 12:37:44

【Codeforces 949D】Shake It! 【动态规划】的相关文章

Codeforces 830D Singer House - 动态规划

It is known that passages in Singer house are complex and intertwined. Let's define a Singer k-house as a graph built by the following process: take complete binary tree of height k and add edges from each vertex to all its successors, if they are no

Codeforces 834D The Bakery - 动态规划 - 线段树

Some time ago Slastyona the Sweetmaid decided to open her own bakery! She bought required ingredients and a wonder-oven which can bake several types of cakes, and opened the bakery. Soon the expenses started to overcome the income, so Slastyona decid

Codeforces 837D Round Subset - 动态规划 - 数论

Let's call the roundness of the number the number of zeros to which it ends. You have an array of n numbers. You need to choose a subset of exactly k numbers so that the roundness of the product of the selected numbers will be maximum possible. Input

Codeforces 1000G Two-Paths 树形动态规划 LCA

原文链接https://www.cnblogs.com/zhouzhendong/p/9246484.html 题目传送门 - Codeforces 1000G Two-Paths 题意 给定一棵有 $n(2\leq n\leq 3\times 10^5)$ 个节点的树,其中节点 $i$ 有权值 $a_i$,边 $e$ 有权值 $w_e$.$(1\leq a_i,w_e\leq 10^9)$ 现在给出 $q(1\leq q\leq 4\times 10^5)$ 组询问,每组询问给定两个数 $x,

CodeForces 429B Working out 动态规划

Description Summer is coming! It's time for Iahub and Iahubina to work out, as they both want to look hot at the beach. The gym where they go is a matrix a with n lines and m columns. Let number a[i][j] represents the calories burned by performing wo

【动态规划】Codeforces 699C Vacations

题目链接: http://codeforces.com/problemset/problem/699/C 题目大意: N天,A(健身)或B(做比赛)或休息,每天都有4种情况,A可行B可行,A可行B不行,A不行B可行,AB都不行. 每天选择一种,不能连续两天选择同一种活动(可以连续休息),问最少休息几天. 题目思路: [动态规划] f[i][j]表示前i天,最后一天状态为j的最多休息天数(最少天数也行),j=0,1,2表示休息,运动和做比赛. 转移方程挺好推的. 1 // 2 //by coolx

动态规划,就是这样! CodeForces 433B - Kuriyama Mirai&#39;s Stones

Kuriyama Mirai has killed many monsters and got many (namely n) stones. She numbers the stones from 1 to n. The cost of the i-th stone is vi. Kuriyama Mirai wants to know something about these stones so she will ask you two kinds of questions: She wi

Codeforces 506E Mr. Kitayuta&#39;s Gift (矩阵乘法,动态规划)

描述: 给出一个单词,在单词中插入若干字符使其为回文串,求回文串的个数(|s|<=200,n<=10^9) 这道题超神奇,不可多得的一道好题 首先可以搞出一个dp[l][r][i]表示回文串左边i位匹配到第l位,右边i位匹配到第r位的状态数,可以发现可以用矩阵乘法优化(某人说看到n这么大就一定是矩阵乘法了= =) 但这样一共有|s|^2个节点,时间复杂度无法承受 我们先把状态树画出来:例如add 可以发现是个DAG 我们考虑把单独的每条链拿出来求解,那么最多会有|s|条不同的链,链长最多为|s

Codeforces 37D Lesson Timetable - 组合数学 - 动态规划

题目传送门 神奇的门I 神奇的门II 题目大意 有$n$组学生要上课2次课,有$m$个教室,编号为$1$到$m$.要确定有多少种不同的安排上课的教室的方案(每组学生都是本质不同的),使得它们满足: 每组学生第一次上课的教室的编号小于等于第二次上课的教室的编号. 第$i$间教室在第一次上课时,恰好有$x_{i}$组学生在场. 第$i$间教室在某次上课时,中间包含的学生组数不能超过$y_{i}$. 输出答案模$10^{9} + 7$. 因为第一次上课恰好有多少人,所以这个方案数是可以直接用组合数,暂