前缀?
(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。
(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); }