牛客多校一 E.ABBA

原题地址:https://ac.nowcoder.com/acm/contest/881/E

思路:定义 d p [ i ] [ j ] dp[i][j] dp[i][j]表示有 i i i A A A, j j j B B B的方案数.
首先,这样子定义,转移就很容易写,你就枚举当前串后面再添一个 A A A还是 B B B,所以也就是

dp[i + 1][j] += dp[i][j];
dp[i][j + 1] += dp[i][j];

所以现在的问题是如何确定一个串是由 n n n A B AB AB并且由m个 B A BA BA

我们考虑之前 d p dp dp定义的前缀 i i i A A A j j j B B B,进一步思考如果 i − j > k i-j>k ij>k,那么这个串至少会产生 k k k A B AB AB(因为如果在某个前缀的时候你 i − j = k i-j=k ij=k,那么必然有 k k k A A A只能与后面的 B B B匹配),同理, j − i j-i ji也是一样的.

所以对于题目中描述的 n n n A B AB AB, m m m B A BA BA,只需要 d p dp dp时候注意合法的转移就可以了.也就是说 i − j > n i-j>n ij>n并且 j − i > m j-i>m ji>m,每次转移的注意一下就可以了.

#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
ll dp[2004][2005];
//dp[i][j]表示前缀有i个A,有j个B的方案数
int main() {
    int n, m;
    while (~scanf("%d%d", &n, &m)) {
       for(int i=0;i<=n+m;i++){
        for(int j=0;j<=n+m;j++) dp[i][j]=0;
       }
        dp[0][0] = 1;
        for (int i = 0; i <= n + m; i++) {
            for (int j = 0; j <= m + n; j++) {
                if (i - j < n)dp[i + 1][j] += dp[i][j];
                if (j - i < m)dp[i][j + 1] += dp[i][j];
                dp[i + 1][j] %= mod;
                dp[i][j + 1] %= mod;
            }
        }
        printf("%lld\n", dp[n + m][n + m]);
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值