2018.5.23 T1前缀?

前缀?
(a.cpp/c/pas)
Time Limit:1 Sec Memory Limit:128 MB
Description
黛黛忙问:“不知老太太做的是什么题?”那丫鬟答道:“说来话长。老太太认为一
个长度为N 的仅由‘0’、‘1’、‘2’三个字符组成的字符串是贾家的,当且仅当这个字
符串满足以下几点:
①这个字符串的所有前缀(不包括这个串本身)都是贾家的。
②这个字符串中字符‘2’出现的个数不少于字符‘1’出现的个数。
③这个字符串中字符‘1’出现的个数不少于字符‘0’出现的个数。
请你求出有多少个长度为N 的字符串是贾家的,由于答案可能很大,你只需要给出答
案mod 1,000,000,007 的值。
题目大概就是这样,黛姑娘还是快进房吧,不然老太太等急了。”
Input
第一行一个正整数N,表示字符串的长度。
Output
输出一个正整数,表示答案。
Sample Input
3
Sample Output
4
Sample Explanation
这4 个字符串分别为“221”、“212”、“210”、“222”。
Data Limitation
对于20%的数据:N≤10。
对于50%的数据:N≤20。
对于80%的数据:N≤300。

对于100%的数据:N≤400。

————————————————————————————————————

前两题题目巨长,是红楼梦选段,自行脑补

一眼就是DP,f[i][j][k]表示第i位,0与1的差为j,1与2的差为 k 的方案数

假设此位为0,0与1的差减一,f[i][j][k]+=f[i-1][j+1][k], 

假设此位为1,0与1的差加一,1与2的差减一,f[i][j][k]+=f[i-1][j-1][k+1], 

假设此位为2,1与2的差加一,f[i][j][k]+=f[i-1][j][k-1], 

最后发现内存会爆炸,把第一维压一下就可以了

#include <cstdio>
#include <algorithm>
using namespace std;
const int N=405,P=1000000007;
int f[2][N][N];
int n,ans;
int main() {
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	scanf("%d",&n);
	f[0][0][0]=1;
	for (int i=1;i<=n;i++) {
		for (int j=0;j<=i;j++)
			for (int k=0;k<=i;k++) {
				f[1][j][k]=0;
				f[1][j][k]=(f[1][j][k]+f[0][j+1][k])%P;
				if (j>0) f[1][j][k]=(f[1][j][k]+f[0][j-1][k+1])%P;
				if (k>0) f[1][j][k]=(f[1][j][k]+f[0][j][k-1])%P;
			}
		for (int j=0;j<=i;j++)
			for (int k=0;k<=i;k++)
				f[0][j][k]=f[1][j][k];
	}
	for (int i=0;i<=n;i++)
		for (int j=0;j<=n;j++)
			ans=(ans+f[1][i][j])%P;
	printf("%d",ans);
}


猜你喜欢

转载自blog.csdn.net/qq_41893580/article/details/80424565
t1