[SDOI2009] Bill的挑战 (状压DP)
1.数塔2.[洛谷P2014] 选课3.玉蟾宫 (悬线DP)4.MooFest POJ-1990 (树状数组)5.情书密码 (树状数组)6.[SCOI 2009] 迷路 (矩阵快速幂)7.[BZOJ3306] 树8.[NOI2002] 荒岛野人9.SHUFFLE 洗牌 (扩展欧几里得+龟速乘)
10.[SDOI2009] Bill的挑战 (状压DP)
11.P4168 [Violet] 蒲公英 (莫队的强制在线)12.P3667 [USACO17OPEN] Bovine Genomics G (set容器+二分)13.P7903 兜心の顶(构造)14.[BZOJ2720 Violet 5]列队春游(概率期望+组合数学)15.划分大理石(多重背包)16.P5746 [NOI2002] 机器人M号17.苍与红的试炼(数位DP)18.【唐赛】高一小学期219.P10779 BZOJ4316 小 C 的独立集 (仙人掌DP)20.关于求合法括号子序列个数[SDOI2009] Bill的挑战
题目描述
Sheng_bill 不仅有惊人的心算能力,还可以轻松地完成各种统计。在昨天的比赛中,你凭借优秀的程序与他打成了平局,这导致 Sheng_bill 极度的不满。于是他再次挑战你。这次你可不能输。
这次,比赛规则是这样的:
给出 ?
组成),
若字符串
。- 对于任意的
,满足 或者 。
其中
输入格式
本题包含多组数据。
第一行一个整数
对于每组数据,第一行两个整数,
接下来
输出格式
每组数据输出一行一个整数,表示答案。
样例 #1
样例输入 #1
5
3 3
???r???
???????
???????
3 4
???????
?????a?
???????
3 3
???????
?a??j??
????aa?
3 2
a??????
???????
???????
3 2
???????
???a???
????a??
样例输出 #1
914852
0
0
871234
67018
提示
数据规模与约定
- 对于
的数据, , ; - 对于
的数据, , ; - 对于
的数据, , , 。
分析
题目给的
不会有人和我一样一眼没看出来吧
看眼数据不难想到应该枚举位数,那么维护数组
定义
所以
首先枚举位数,然后枚举状态
如果
之后枚举字符,在下一状态下添加字符的种类数为本状态加上下一状态的原种类数
得到的状态转移方程即为
最后枚举不同状态,记录该状态与原数组的匹配情况
判断该状态是否包括某一行的位数(即该行匹配)
如果是则
最后别忘了要取mod
code
Elaina's code
#include<bits/stdc++.h>
using namespace std;
const int N=50100;
const double eps=1e-8;
#define int long long
#define inf 0x3f
#define INF 0x3f3f3f3f
#define mst(a,b) memset(a,b,sizeof(a))
#define re register
#define Elaina 0
inline int read(){
int x=0,f=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
return x*f;
}
int mod=1e6+3;
int dp[55][1<<15],g[55][30];
char s[16][55];
int T,n,m;
main(){
T=read();
while(T--){
mst(dp,0);
mst(g,0);
n=read(),m=read();
for(int i=0;i<n;i++){
scanf("%s",s[i]);
}
int len=strlen(s[0]);
for(int i=0;i<len;i++){//位数
for(int j=0;j<26;j++){//字符
for(int k=0;k<n;k++){//行数
if(s[k][i]=='?'||s[k][i]==j+'a'){
g[i][j]|=(1<<k);//匹配情况
}
}
}
}
dp[0][(1<<n)-1]=1;
for(int i=0;i<len;i++){//位数
for(int j=0;j<(1<<n);j++){//状态
if(dp[i][j]){
for(int k=0;k<26;k++){//字符
dp[i+1][j&g[i][k]]=(dp[i+1][j&g[i][k]]+dp[i][j])%mod;
}
}
}
}
int ans=0;
for(int i=0;i<(1<<n);i++){//状态
int tot=0;
for(int j=0;j<n;j++){
if(i&(1<<j)){
tot++;
}
}
if(tot==m){
ans=(ans+dp[len][i])%mod;
}
}
printf("%lld\n",ans);
}
return Elaina;
}
/*
5
3 3
???r???
???????
???????
3 4
???????
?????a?
???????
3 3
???????
?a??j??
????aa?
3 2
a??????
???????
???????
3 2
???????
???a???
????a??
*/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本