题目链接

大致题意

有(n+m)(n + m)(n+m)个字母A和(n+m)(n + m)(n+m)个字母B,组成一个长度为 2∗(n+m)2*(n + m)2∗(n+m)的字符串,并且使得字符串中有nnn个“AB”和mmm个“BA”,求出可能的组合数(mod 1e9+7)

例如,n = 1 m = 2时,可以有这样的字符串(并不是全部的字符串):

ABBABA

ABBBAA

BBABAA

上面三个字符串均满足条件

解题思路

考虑递推,假设已经有一个字符串满足一定的“先决条件”(此处应当理解为数学归纳法,及假设n - 1时满足)

下面考虑在字符串最后加入一个字符的情况。仅有两种可能:加A或者加B(这不是白说吗)

但是考虑一下极端情况,我们可以得到一些简单的且明显的条件(NA表示已经在字符串中的A个数,NB同理)

假如字符串的组成类似这样:

AAAAABBBBBBBB

则此字符串中,只能组合出 AB 而不可能组合出 BA

此时,我们假设 nnn 为 5

而这个字符只能且必定要组合成 5 个AB,也就是说,我们接下来加入字符,只能加入 A 而不能加入 B

此时我们往前推,如果出现了这样一个字符串,则在之前,必定出现如下状态:

AAAAA

也即是 5 个A的情况,此时我们可以得到一个确定的关系式:

NB = 0 and NA <= n

推广到有B的情况,最优的情况就是所有的B都是用来组成BA,那么可以得到我们真正需要的关系式:

NA - NB <= n

同理,相对于 B 而言,我们可以得到

NB - NA <= m

合并上述两式

-n < NA - NB <= m

所以根据下标为 NA - NB 建立DP数组,下标范围为 -n 到 m (均包含)DP的内容为方案数量(mod 1e9 + 7),递推公式为

dp[i]=dp[i−1]+dp[i+1]dp[i] = dp[i - 1] + dp [i + 1]dp[i]=dp[i−1]+dp[i+1]

其中,dp[i - 1]指的是加入一个B(增加一个B使得NA - NB变小)。而dp[i + 1]指的是加入一个A

当考虑到无论是正向dp还是逆向dp,均有值优先于dp[i]先更新(dp[i - 1]和dp[i + 1]会比dp[i]先更新),所以采用两个dp数组的方式,初始值dp[0]=1。每两次dp完后,dp[0]的值及为答案。

AC代码

#include <bits/stdc++.h>

using namespace std;

#define MAXN 2100
#define MOD (int)(1e9 + 7)
typedef long long ll; ll dp[MAXN][2]; int trans(int x) {
return x + 1000;
} int main()
{
#ifdef ACM_LOCAL
freopen("debug.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
int n, m;
while (cin >> n >> m) {
memset(dp, 0, sizeof(dp));
dp[n][1] = 1;
int cur = 0;
int last = 1;
for (int i = 0; i < 2 * (n + m); i++) {
for (int j = -n; j <= m; j++) {
if (j != -n) {
dp[j + n][cur] += dp[j - 1 + n][last];
dp[j + n][cur] %= MOD;
}
if (j != m) {
dp[j + n][cur] += dp[j + 1 + n][last];
dp[j + n][cur] %= MOD;
}
}
for (int j = -n; j <= m; j++) {
dp[j + n][last] = 0;
}
swap(cur, last);
}
cout << dp[n][last] << endl;
}
return 0;
}

最新文章

  1. ORACLE等待事件: log file parallel write
  2. Lucene索引文件学习
  3. .Net 高效开发之不可错过的实用工具(转)
  4. android studio gradle升级
  5. COFF/PE文件结构
  6. 添加Action View
  7. KMP算法 --- 在文本中寻找目标字符串
  8. 使用控制台调试WinForm窗体程序
  9. Netty中的EventLoop和线程模型
  10. win7下怎么安装IIS
  11. 【Unity游戏开发】用C#和Lua实现Unity中的事件分发机制EventDispatcher
  12. JavaScript—Date对象详情
  13. [转] web前端js构造无法销毁的类UUID识别码,识别浏览器设备唯一性
  14. 使用VS2015编译grpc_1.3.1
  15. WebDriver一些常见问题的解决方法
  16. RAMOS_XP制作教程
  17. 11 Go 1.11 Release Notes
  18. Becoming inspired (2) - ASC 2017 March 25
  19. Android响应式UI教程
  20. create a nodejs npm package

热门文章

  1. CentOS7用yum安装wget命令后仍然提示命令找不到的解决方法
  2. Laravel Study(使用 Laravel )
  3. hexo及next主题修改
  4. Cenots 7 安装mysql cluster 通过rpm 包
  5. C++中cin的输入分隔符问题及相关
  6. SpringBoot图文教程9—SpringBoot 导入导出 Excel 「Apache Poi」
  7. Java设计模式二
  8. 微信小程序状态管理工具 JStore
  9. Rxjs入门实践-各种排序算法排序过程的可视化展示
  10. [转帖]RSYNC 的核心算法