用流程描述合法状态

  我似乎记得 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$ 的方案数。

时间: 2024-11-12 01:23:34

用流程描述合法状态的相关文章

C++学习:任意合法状态下汉诺塔的移动(原创)

汉诺塔问题: 问题是源于印度一个古老传说的益智玩具.大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘.大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上.并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘. 现在将问题变形为:初识时,n个金盘分散摆放在三根柱子上,并且所有金盘都处于合法状态,将这些分散的金盘全部移动到第三根柱子上,并打印每一次的移动步骤以及移动后三个柱子上金盘的状态. C++实现代码如下: 1 #ifnde

流程一直处于Running状态,应该怎么停止?

流程一直处于Running状态,应该怎么停止? 概述 我们有遇到这种情况:可能由于某些原因,流程发起后一直处于Running状态,然后我们想Stop掉这些出问题的流程,这个时候你在Workspace里面进行操作,这个操作是不可能完成的,Workspace也会一直处于Loading状态. 这种情况下,您唯一的选择就是通过更新K2 Database来停止这些流程. 在执行这些操作之前,应该尝试通过Workspace停止流程实例,只有在Workspace处理不了的时候,才去更新K2 Database

身份认证流程描述

1.1.1          身份认证 每个用户都持有可唯一标识用户身份的私钥和由CA签发的公钥证书,用户私有信息保存在电子钥匙(USBKEY)或其它安全载体中.在访问应用系统时,用户出示自已的身份证明(签名和证书),实现基于证书的身份认证过程. 身份认证分为单向或双向认证方式,在一般情况下采用服务器认证客户的单向认证方式,在必要时可采用双向认证方式. 应用系统中,应用服务程序直接通过安全接口调用认证服务器对用户进行身份认证,用户身份信息由应用系统自身进行维护和管理. 应用系统服务器端和客户端各

RoseMirror人为停机后,恢复流程描述

Q: 问题描述: server1主,server2备server1出了问题,集群切换到server2,但是server2的web访问不了,然后客户就把rose服务给停了,然后手动启动server1的应用,附加ip地址,用了一段时间后,要把集群用上;此时server1是最新数据,但是server2是主机角色 带出状态 我让他做一下转移,提示有数据更新,转移不成功,然后我让他选择数据源,然后让server1同步server2数据 同步数据源完成后,应用和ip都没有带起来 而且也没有报错 客户反馈的,

编写Python爬虫的简易流程描述

python网络爬虫,其实就是模拟人类浏览网页的行为,并将这种行为自动化的工具. 从技术上来说,就是利用python代码发送特定的request请求到Web页面,最后获得response,并将response解析,提取其中的数据并存储起来. 开发一个爬虫程序,首先要确定目标.例如爬取拉勾网的python相关职位信息是我们的目标.根据这个目标,我们可以先使用手工的方式,访问拉勾网,搜索python相关职位,从而对如何从页面获取所需信息有一个直观的理解. 其次,可以使用浏览器自带的开发者工具.抓包工

易拓展、易修改的状态流程设计和实现

1,前言 Workflow(https://en.wikipedia.org/wiki/Workflow)是一个极其常见的业务场景,基本所有行业都能涉及到流程管理上的问题.工作流,个人认为可以等价的理解为状态流(state flow),因为工作流的主要工作就是流程管理或者就是状态转移.如果用状态转移来抽象描述问题的话,基本大多数业务系统都可以状态转移来描述,且不说OA.ERP等软件,在常见交易系统软件里产品管理的流程.在线交易系统里订单的各个状态流程等. 使用状态转移来描述问题的优势是语义简洁.

Android 4.4 Kitkat Phone工作流程浅析(九)__状态通知流程分析

本文来自http://blog.csdn.net/yihongyuelan 转载请务必注明出处 本文代码以MTK平台Android 4.4为分析对象,与Google原生AOSP有些许差异,请读者知悉. 前置文章: <Android 4.4 Kitkat Phone工作流程浅析(一)__概要和学习计划> <Android 4.4 Kitkat Phone工作流程浅析(二)__UI结构分析> <Android 4.4 Kitkat Phone工作流程浅析(三)__MO(去电)流程

netstat状态详解

一.生产服务器netstat tcp连接状态................................................................................ 2 1.1生产服务器某个业务LVS负载均衡上连接状态数量............................................... 2 1.2生产服务器某个业务web上连接状态数量...............................................

uml系列(六)——行为图:活动&amp;状态

说完uml的静态图了,说一下uml的动态的表示吧. uml的行为图,uml的行为图主要用来设计程序的行为.还是老规矩,先来张图: 行为图包含活动图和状态图两种. 先来说下活动图:活动图是由活动的节点和流程构成的图.比较清晰的表达了各个步骤的流程. 首先是起点和终点,活动图由一个实心圆表示起点,一个实心圆外加一个圆圈来表示终点. 然后是节点,节点这个词比较高大上,其实它很简单,就是说的流程进行的状态,进行到哪一步了.上图的"用户下订单"."生产送货单"等都是节点. 在