码迷,mamicode.com
首页 > 其他好文 > 详细

用流程描述合法状态

时间:2017-11-05 17:28:44      阅读:148      评论:0      收藏:0      [点我收藏+]

标签:alpha   ext   log   依次   类型   过程   center   div   海阔天空   

  我似乎记得 Polya 的《怎样解题表》提示我 “从尽可能多不同的角度将原问题进行描述” ,也似乎记得有某篇集训队论文的题目叫做《退一步,海阔天空》 ,我想,用一个流程来对题目中的合法状态进行描述,能获得许多不一样的理解吧。

  就目前做的题来看,这种观点大多用于计数问题,或者一些最优性问题。

 

[TH 2140] 计数

  给 $n_1(\le 1000)$ 个 $A$ 、$n_2(\le 1000)$ 个 $B$ 、$n_3(\le 1000)$ 个 $C$ 、$n_4(\le 1000)$ 个 $D$ ,求能组成多少个相邻项不同的序列。

  用一个流程描述所有序列,然后对流程的不同运行数进行计数:对 $A$ 与 $B$ 归并,对 $C$ 与 $D$ 归并,然后将两个序列相互渗入。

  两个序列不一定能够相互渗入。对由两种字母构成的序列定义渗入指数 $K$ :强制把序列钦定为 $K$ 段,相互渗入的时候在两段之间的空隙必须插入。那么两个序列能够相互渗入,当且仅当渗入系数的差值的绝对值不超过 $1$ 。

  如何求由 $n_1$ 个 $A$ ,$n_2$ 个 $B$ ,构造的渗入系数为 $K$ 的序列个数?

  观察性质发现,对于每一段,只可能有三种情况:

  (1)$A$ 比 $B$ 多 $1$ 个;

  (2)$B$ 比 $A$ 多 $1$ 个;

  (3)$A$ 和 $B$ 一样多。

  枚举 $A$ 比 $B$ 多 $1$ 个的段数 $a$ ,可以解决 $B$ 比 $A$ 多 $1$ 个的段数 $b$ ,以及 $A$ 、$B$ 一样多的对数 $c$ 。

  通过 $\binom{K}{a, b}$ 钦定哪些段是情况(1)(2),然后乘上 $2 ^ {K - a - b}$ 钦定 $A$ 、$B$ 一样多的段数是形如 $ABAB$ 还是 $BABA$ 。剩下的问题就是将 $c - (K - a - b)$ 对 $ab$ 划分到 $K$ 段中,这是经典的不定方程计数,利用插板法。

 1 const int N = 2005;
 2 const int MOD = 1e9 + 7;
 3 
 4 int C[N][N], Pow[N];
 5 int n1, n2, n3, n4;
 6 int f[N], g[N], ans;
 7  
 8 inline int Solu(int n, int m) {
 9     // a[1] + a[2] + ... + a[n] = m, a[i] >= 0
10     if (n == 0) return m == 0;
11     return C[m+n-1][n-1];
12 }
13 void Init(int nA, int nB, int *h) {
14     F(K, 0, nA+nB) {
15         F(a, 0, K) {
16             int b = nA - nB + a;
17             int c = K - a - b;
18             int d = (nA + nB - a - b) >> 1;
19             if (!(a >= 0 && b >= 0 && c >= 0 && d >= c)) continue;
20             h[K] = (h[K] + 1LL * C[K][a] * C[K-a][b] % MOD * Solu(K, d-c) % MOD * Pow[c]) % MOD;
21         }
22     }
23 }
24 
25 int main(void) {
26     For(i, 0, N) {
27         C[i][0] = 1;
28         F(j, 1, i) C[i][j] = (C[i-1][j] + C[i-1][j-1]) % MOD;
29     }
30     Pow[0] = 1;
31     For(i, 1, N) Pow[i] = (Pow[i-1] << 1) % MOD;
32     
33     scanf("%d %d %d %d", &n1, &n2, &n3, &n4);
34     Init(n1, n2, f);
35     Init(n3, n4, g);
36     
37     F(i, 1, n1+n2)
38         ans = (ans + 1LL * f[i] * g[i-1] + 2LL * f[i] * g[i] + 1LL * f[i] * g[i+1]) % MOD;
39     printf("%d\n", ans);
40 }

 

[HDU 6017] Girl Love 233

  给长度为 $n(\le 100)$ 的由 $2$ 、$3$ 组成的序列,求对序列进行不超过 $m(m \le 100)$ 次交换相邻两位的所有新序列中,最多的连续的 $233$ 的个数。

  所有新序列可以看作:由 $2$ 、$3$ 归并而成,且最少的交换次数小于等于 $m$ 。即设原序列 $2$ 的位置为 $a_1, a_2, ..., a_k$ ,新序列 $2$ 的位置为 $b_1, b_2, ..., b_k$ ,则要求 $\sum |a_i - b_i| \le m$ 。

  设 $f[i][j][k][l]$ 表示在归并的过程中,用了 $i$ 个 $2$ 、$j$ 个 $3$ 、$k$ 次交换、末尾状态为 $l$ 的最多的连续的 $233$ 个数,DP 即可。

 

[BZOJ 3864] Hero meet devil

  字符集为 $\left\{ ‘A‘, ‘G‘, ‘C‘, ‘T‘ \right\}$ ,给长度为 $n(\le 15)$ 的字符串 $S$ ,求有多少个长度为 $m(\le 1000)$ 的字符串 $T$ ,使得 $LCS(S, T) = 0, 1, ..., n$ 。

  如何求 $LCS(S, T)$ ?设 $f[i][j]$ 表示 $LCS(T[1:i], S[1:j])$ ,由 $f[i-1][]$ 推出 $f[i][]$ 。换句话说,假如把每一行当作一种变量类型命名为 $T$ 的状态,那么我由 $f[0]$ 推得 $f[1]$ ,$f[1]$ 推得 $f[2]$ ,依次类推。综上,用了一个流程来描述 $LCS(S, T)$ 。

  对这个流程套用 DP ,设 $g[i][State]$ 表示考虑到第 $i$ 位的状态,且 $f[i] = State$ 的方案数。

  在 $State$ 中,相邻两位的差值为 $0$ 或 $1$(可以通过数学归纳法进行证明),且第一位的值为 $0$ ,所以可以通过二进制来表示所有的状态,且状态数为 $O(2 ^ n)$ 。

 

[CF 578D] LCS Again

  字符集 $\alpha = \left\{ 前 m 个小写字母 \right\}$ ,给长度为 $n(\le 100000)$ 的串 $S$ ,求有多少个串 $T$ ,使得 $LCS(S, T) = n-1$ 。

  对于给定的 $S, T$ ,如何判断 $S, T$ 的 $LCS$ 是否为 $n-1$ ?假设 $S, T$ 的 $LCS$ 为 $n-1$ ,设 $f[i][j]$ 表示 $T[1 : i]$ 与 $S[1 : j]$ 的 $LCS$ ,$f[i][j] = \min(f[i-1][j], f[i][j-1], f[i-1][j-1] + [ T_i = S_j ])$ ,但是这样的判定是 $O(n ^ 2)$ 的,实在不可取。

  将 $f[][]$ 理解为二维平面上的 $n \times n$ 个点,定义横向边、纵向边的边权为 $0$ ,对角边的边权为 $1$ ,问从 $(0, 0)$ 走到 $(n, n)$ 的最大边权之和是否为 $n-1$ 。假设一条从 $(0, 0)$ 走到 $(n, n)$ 的路径经过了 $(i, j)$ ,那么边权之和的最大值为 $Max = \min(i, j) + \min(n - i, n - j) = n - \max(i, j) + \min(i, j)$ ,那么要求 $Max \ge n-1$ ,所以 $|i - j| \le 1$ 。所以,对于 $|i - j| > 1$ ,对答案没有贡献,只需要维护 $f[i][i-1], f[i][i], f[i][i+1]$ 即可。且任何时候如果 $f[i][i]$ 不等于 $i$ 或 $i-1$ ,那么 $f[i][i] < i-1$ ,对答案也没有贡献,直接宣告判断失败。

  把一行看作一个整体的状态,我由 $f[0]$ 推出 $f[1]$ ,$f[1]$ 推出 $f[2]$ ,依次类推。设 $g[i][S]$ 表示推到 $f[i]$ ,且 $f[i] = S$ 的方案数,对 $g$ 进行 DP 。由于 $S$ 满足 $f[i][i] = i$ 或 $f[i][i] = i-1$ ,且 $f[i][i] - f[i][i-1] \le 1$ ,$f[i][i+1] - f[i][i] \le 1$ ,所以可以使用 $2 ^ 3$ 个二进制状态进行表示,总的时间复杂度为 $O(2 ^ 3 nm)$ 。

 

[TH 1587] 小方格

  给 $n \times n(n \le 8)$ 的方格,有坏点。对剩下的格子进行黑白染色,问最大纯白色正方形边长为 $0, 1, ..., n$ 的方案数。

  差分,转化为求最大纯白色正方形边长小于等于 $x$ 的方案数 $ans[]$ 。

  对于给定的染色方案,如何判定最大纯白色正方形的面积是否小于等于 $x$ ?逐行扫描,维护 $S = \left\{ s_1, s_2, ..., s_{n - x} \right\}$ ,$s_i$ 表示扫描到当前行时,第 $i, i+1, i+2, ..., i+x$ 列共同隆起的长度,当 $s_i = x+1$ 时,判定失败。

  设 $g[i][T]$ 表示扫描到第 $i$ 行,当前的 $S = T$ 的方案数。$S$ 用长度为 $n-x$ 的 $x+1$ 进制数进行表示。

 

[TH 1305] 填格子

   $2 \times m(m \le 1000000)$ 的格子,填 $A$ 、$B$ 、$C$ ,满足:

  (1)田字格中,每种颜色都出现过;

  (2)相邻颜色不同;

  (3)$A$ 有 $a$ 个、$B$ 有 $b$ 个、$C$ 有 $c$ 个,保证 $r + g + b = 2m$ 。

  把满足(1)(2)的状态称为合法状态。确定相邻互不相同的第一行,再确定第一行与第二行的对应关系,可以不重不漏地描述出所有的合法状态

  第一行与第二行的对应关系有两种:

第一种

第二种
A B C A B C
| | | | | |
C A B B C A

  对满足第一种对应关系、满足(3)的合法状态个数进行计数:设有 $x$ 个 $A$ 对应 $C$ ,$y$ 个 $B$ 对应 $A$ ,$z$ 个 $C$ 对应 $B$ ,合法当且仅当 $x + y = a, y + z = b, z + x = c$ ,可以唯一地解得 $(x, y, z) = (m - a, m - b, m - c)$ ,所以只需要求将 $x$ 个 $A$ 、$y$ 个 $B$ 、$z$ 个 $C$ 排成一排,且相邻两个不同的方案数,可以用 [TH 2140] 计数 一题的方法做。

  对满足第二种对应关系,$(x, y, z)$ 的解相同,把第一次的答案乘 $2$ 即可。

 

[TH 1841] Intervals

  在长度为 $m$ 的序列选 $n$ 个互不包含的区间,且点 $x$ 不能作为区间的左端点,求方案数。

  $n \times m \le 100000$ 。

  以每个点作为左端点(右端点),最多只有一个区间,否则包含。所以若合法,那么 $n \le m$ ,所以 $n \le 500$ 。

  用流程描述合法选择方案:从左往右扫描,时刻维护左端点队列 $Q$ ;扫到每个点的时候,可以在这个点建立一个左端点,将左端点加入 $Q$ ,可以在这个点建立一个右端点,将 $Q$ 的队头与当前点匹配;扫描完之后 $Q$ 空。

  对这个流程进行 DP ,$f[i][j][k]$ 表示当前扫描到了第 $i$ 个点,已经确定了 $j$ 个区间的左端点,当前队列中有 $k$ 个区间的左端点的方案数。边界为 $f[0][0][0] = 1$ ,答案为 $f[m][n][0]$ ,转移分 "是否建立左端点" 、"是否建立右端点" 共四类讨论。

 

[AGC 002F] 球

  有 $n(\le 2000)$ 种颜色的球,每种各有 $K(\le 2000)$ 个,将这 $n \times K$ 个球排成一列,将每种球的第一个染成颜色 $0$ ,问可能得到多少种不同的颜色序列。

  钦定第一次出现的球的顺序:第 $1$ 个第一次出现的球的颜色为 $1$ 、第 $2$ 个第一次出现的球的颜色为 $2$ 、...、第 $n$ 个第一次出现的球的颜色为 $n$ ,然后对答案乘上 $n!$ 。

  可以通过这样一个流程来描述最终的染色序列:从 $n$ 到 $1$ 枚举颜色 $i$ ,每次将 $K-1$ 个颜色 $i$ 的球和 $1$ 个颜色为 $0$ 的球插入序列中,保证 $0$ 插在序列的开头,第一个 $i$ 要在第一个 $i+1$ 之前。

  受此启发,直接 DP :设 $f[i][j]$ 表示考虑了颜色 $[n-i+1, n]$ ,序列的开头有 $j$ 个 $0$ 的方案数。

用流程描述合法状态

标签:alpha   ext   log   依次   类型   过程   center   div   海阔天空   

原文地址:http://www.cnblogs.com/Sdchr/p/7787695.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!