标签:out span 问题 数组 def namespace http 前缀 mod
括号序列问题,往往就是把左括号看成+1,右括号看成-1,我们只需要保证任意一个前缀大于等于0,且总和为0,就代表是个合法括号序列了。
令\(f[i][j]\)表示当前到第\(i\)个字符,现在的前缀和\(j\)。那么分三种情况考虑。
若第\(i+1\)个字符是左括号,则能转移到\(f[i+1][j+1]\)。
若第\(i+1\)个字符是右括号,则能转移到\(f[i+1][j-1]\)。
若第\(i+1\)个字符是问号,则能转移到\(f[i+1][j-1]\)与\(f[i+1][j+1]\)。
最终\(f[n][0]\)就是方案总数啦。
时间复杂度为\(O(n^2)\)。
优化:
二维数组一定会炸。。。。
那就。。。循环队列!
我们发现每次到新的一个 $i $,它只和 \(i-1\) 有关,所以 \(i-1\) 用过一次就可以销毁了,不然也是占空间
可以像这样&1?来实现循环利用
f[i & 1][0]=0
STD
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
int n;
int f[3005][3005];
char c[3005];
int main()
{
scanf("%d",&n);
scanf("%s",c+1);
f[0][0]=1;
for(int i=1;i<=n;i++)
{
if(c[i]==‘Y‘)
{
for(int j=1;j<=i;j++)
{
f[i][j]=f[i-1][j-1];
}
}
if(c[i]==‘H‘)
{
for(int j=0;j<i;j++)
{
f[i][j]=f[i-1][j+1];
}
}
if(c[i]==‘C‘)
{
f[i][0]=f[i-1][1];
for(int j=1;j<i;j++)
{
f[i][j]=(f[i-1][j+1]+f[i-1][j-1])%mod;
}
f[i][i]=f[i-1][i-1];
}
}
cout<<f[n][0]%mod;
}
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
int n;
int f[3][10005];
char c[10005];
int main()
{
freopen("data10.in","r",stdin);
freopen("data10.out","w",stdout);
scanf("%d",&n);
scanf("%s",c+1);
memset(f,0,sizeof(f));
f[0][0]=1;
for(int i=1;i<=n;i++)
{
if(c[i]==‘Y‘)
{
f[i&1][0]=0;
for(int j=1;j<=i;j++)
{
f[i&1][j]=f[(i-1)&1][j-1];
}
}
if(c[i]==‘H‘)
{
f[i&1][i]=0;
for(int j=0;j<i;j++)
{
f[i&1][j]=f[(i-1)&1][j+1];
}
}
if(c[i]==‘C‘)
{
f[i&1][0]=f[(i-1)&1][1];
for(int j=1;j<i;j++)
{
f[i&1][j]=(f[(i-1)&1][j+1]+f[(i-1)&1][j-1])%mod;
}
f[i&1][i]=f[(i-1)&1][i-1];
}
}
cout<<f[n&1][0]%mod;
}
标签:out span 问题 数组 def namespace http 前缀 mod
原文地址:https://www.cnblogs.com/lcezych/p/13266794.html