bzoj千题计划207:bzoj1879: [Sdoi2009]Bill的挑战
http://www.lydsy.com/JudgeOnline/problem.php?id=1879
f[i][j] 表示匹配了i个字符,匹配字符串的状态为j的方案数
枚举下一个字符是什么
计算加上这个自字符之后新匹配到的状态s
f[i+1][s]+=f[i][j]
转移的时候判断如果f[i][j]==0,就不用枚举字符了
没有这个复杂度在6e8,TLE
其实可以预处理 g[i][j]表示已经匹配了长度为i,再加字符j 可以匹配到的状态
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=1<<15; const int mod=1000003; char s[16][51]; int f[51][N]; int bit[16]; int count(int x) { int sum=0; while(x) { sum+=x&1; x>>=1; } return sum; } int main() { bit[0]=1; for(int i=1;i<=15;++i) bit[i]=bit[i-1]<<1; int T; scanf("%d",&T); int n,t,m,len; int S,nj; int ans; while(T--) { scanf("%d%d",&n,&t); memset(f,0,sizeof(f)); m=0; for(int i=1;i<=n;++i) { scanf("%s",s[i]+1); len=strlen(s[i]+1); m=max(m,len); } S=bit[n]; for(int i=0;i<26;++i) { nj=0; for(int j=1;j<=n;++j) if(s[j][1]==i+'a' || s[j][1]=='?') nj+=bit[j-1]; f[1][nj]++; } for(int i=1;i<m;++i) for(int j=0;j<S;++j) if(f[i][j]) for(int k=0;k<26;++k) { nj=0; for(int l=1;l<=n;++l) if(j&bit[l-1]) if(s[l][i+1]==k+'a' || s[l][i+1]=='?') nj+=bit[l-1]; f[i+1][nj]+=f[i][j]; f[i+1][nj]-=f[i+1][nj]>=mod ? mod : 0; } ans=0; for(int i=0;i<S;++i) if(count(i)==t) { ans+=f[m][i]; ans-=ans>=mod ? mod : 0; } cout<<ans<<'\n'; } }
1879: [Sdoi2009]Bill的挑战
Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 919 Solved: 477
[Submit][Status][Discuss]
Description
Input
本题包含多组数据。
第一行:一个整数T,表示数据的个数。
对于每组数据:
第一行:两个整数,N和K(含义如题目表述)。
接下来N行:每行一个字符串。
T ≤ 5,M ≤ 15,字符串长度≤ 50。
Output
如题
Sample Input
5
3 3
???r???
???????
???????
3 4
???????
?????a?
???????
3 3
???????
?a??j??
????aa?
3 2
a??????
???????
???????
3 2
???????
???a???
????a??
3 3
???r???
???????
???????
3 4
???????
?????a?
???????
3 3
???????
?a??j??
????aa?
3 2
a??????
???????
???????
3 2
???????
???a???
????a??
Sample Output
914852
0
0
871234
67018
0
0
871234
67018