文章目录
E - Chain Contestant
题意:
给你一个只有
10
10
10个大写字母长度为
n
n
n的字符串
s
s
s,问有多少种非空子序列,使得如果选了一个字符,那么这些字符必须连续出现
思路:状压dp
状态表示:
d
p
i
,
j
,
k
dp_{i,j,k}
dpi,j,k,表示枚举到第
i
i
i个字符,以
j
j
j结尾,
k
k
k表示每字符选和不选的状态,例如
d
p
4
,
3
,
0001001000
dp_{4,3,0001001000}
dp4,3,0001001000表示当前枚举到第四个字符,以3为结尾,当前出现的字符集为3,6
状态转移:
c
u
r
cur
cur表示当前枚举的字符
1.当前不选这个字符,当前状态直接从之前状态转移
d
p
i
,
c
u
r
,
k
=
d
p
i
−
1
,
j
,
k
(
0
≤
j
≤
9
)
(
0
≤
k
≤
1023
)
dp_{i,cur,k}=dp_{i-1,j,k} \space (0\le j\le9)\space (0\le k\le 1023)
dpi,cur,k=dpi−1,j,k (0≤j≤9) (0≤k≤1023)
2.当前只选这个字符,与之前状态无关
d
p
i
,
c
u
r
,
1
<
<
c
u
r
+
=
1
dp_{i,cur,1<<cur}+=1
dpi,cur,1<<cur+=1
3.在之前状态基础上选这个字符
想选这个字符,那么之前状态必须以
c
u
r
cur
cur结尾或者没有出现
c
u
r
cur
cur
如果
k
k
k的第
c
u
r
cur
cur位为
1
1
1,
d
p
i
,
c
u
r
,
k
+
=
d
p
i
−
1
,
c
u
r
,
k
dp_{i,cur,k}+=dp_{i-1,cur,k}
dpi,cur,k+=dpi−1,cur,k
否则
d
p
i
,
c
u
r
,
k
∣
1
<
<
c
u
r
+
=
d
p
i
−
1
,
j
,
k
(
j
≠
c
u
r
)
dp_{i,cur,k|1<<cur}+=dp_{i-1,j,k} (j\neq cur)
dpi,cur,k∣1<<cur+=dpi−1,j,k(j=cur)
(
k
∣
1
<
<
c
u
r
)
(k|1<<cur)
(k∣1<<cur)表示把
k
k
k的第
c
u
r
cur
cur位变成
1
1
1
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define ll long long
#define int ll
#define pb push_back
#define mp make_pair
#define SZ(x) (int)(x.size())
#define ALL(x) (x).begin(),(x).end()
#define mst(a,x) memset(a,x,sizeof(a))
#define ls u<<1
#define rs u<<1|1
typedef vector<int> VI;
typedef pair<int,int> PII;
const int maxn=1e6+10;
const int mod=998244353;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
int n;
char s[1010];
int dp[1010][11][1025];
void solve()
{
cin>>n>>s+1;
rep(i,1,n)
{
int cur=s[i]-'A';
//不选这一位
rep(j,0,9) rep(k,0,1023) dp[i][j][k]=dp[i-1][j][k];
//只选这一位
dp[i][cur][1<<cur]=(dp[i][cur][1<<cur]+1)%mod;
rep(j,0,1023)
{
//字符集里有cur
if(j>>cur&1)
{
dp[i][cur][j]=(dp[i][cur][j]+dp[i-1][cur][j])%mod;
}
else
{
rep(c,0,9)
if(c!=cur) //加上不以cur结尾的状态
dp[i][cur][j|1<<cur]=(dp[i][cur][j|1<<cur]+dp[i-1][c][j])%mod;
}
}
}
int ans=0;
rep(j,0,9) rep(k,0,1023) ans=(ans+dp[n][j][k])%mod;
cout<<ans<<endl;
}
signed main()
{
#ifdef LOCAL
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
//int _;cin>>_;while(_--)
solve();
return 0;
}