(dp)11th福州大学校赛,D.花生的序列

Problem 2170 花生的序列

Accept: 114    Submit: 339
Time Limit: 3000 mSec    Memory Limit : 32768 KB

 Problem Description

“我需要一个案件!!!”,没有案件卷福快疯了。花生不忍心看卷福这个样子,他决定帮卷福找点事情做。

花生拿了两个长度为N的相同的序列,序列都为WB(WBWBWB...)相间,并且由W开头。他将两个序列并在了一起,其中属于同个序列的元素相对位置不变。花生高兴的把新序列拿给卷福,要求卷福给每个元素标上1或2编号,表示这个元素是原来的第几个序列的元素。

卷福看完花生的序列,哭笑不得。“笨蛋!你难道不知道这个标号不唯一么!那你知道有多少种不同的标号方案么?”

可怜的花生给自己挖了个坑。快来帮他解决这个问题!

 Input

输入第一行包含一个整数t,表示输入组数。

每组数据第一行为一个整数N(1<=N<=3000),表示每个原序列的长度。

接下来一行为一个只包含’W’, ’B’的字符串,长度为2*N。

 Output

输出一个整数占一行,为标号的方案数。由于答案比较大,请将答案mod 1000000007。

 Sample Input

3
2
WBWB
2
WWBB
2
BBWW

 Sample Output

2
4
0
/*
链接:http://acm.fzu.edu.cn/problem.php?pid=2170
题意:给你一个长度为2*n的由W和B组成字符串 该字符串是由2个长度为n的并且是WBWBW....形式的 求有多少种组成方案
思路:DP。dp[i][j]:=输入字符串des[i+j]由A[i]、B[i]组成的方案数。由于空间限制,使用滚动数组。
*/
#include <iostream>
#include<cstdio>
#include <cstring>

using namespace std;
#define MOD 1000000007
int dp[2][3002];
char ch[6003];
int main(int argc, const char * argv[])
{

	int t, i, j;
	int n;
	cin >> t;
	while (t--) {
		cin >> n;
		scanf("%s", ch + 1);
		memset(dp, 0, sizeof(dp));
		dp[0][0] = 1;
		for (i = 0; i <= n; i++)
		for (j = 0; j <= n; j++) {
			if (i == 0 && j == 0) continue;
			int sum = 0;
			if (ch[i + j] == 'W') {//'W'只能放到A、B的奇数位置
				if (i & 1)
					sum = (sum + dp[(i - 1 + 2) % 2][j]) % MOD;
				if (j & 1)
					sum = (sum + dp[i % 2][j - 1]) % MOD;

				dp[i % 2][j] = sum%MOD;
			}
			else {//'B'只能放到A、B的偶数位置
				if (i>0 && (i & 1) == 0)
					sum = (sum + dp[(i - 1 + 2) % 2][j]) % MOD;
				if (j>0 && (j & 1) == 0)
					sum = (sum + dp[i % 2][j - 1]) % MOD;

				dp[i % 2][j] = sum%MOD;
			}
		}
		cout << dp[n%2][n] << endl;
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值