[SDOI2009]Bill的挑战
题目描述
题解:
因为要求的T长度一定,可定义f[i][j] 为前i位状态为j的方案,can[i][j]表示第i为字母j,可行的状态 每次往后推就行了
1 #include <algorithm> 2 #include <iostream> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 using namespace std; 8 const int N=55,mod=1000003; 9 int f[N][1<<15],can[55][55];char s[105][105]; 10 int count(int x){ 11 int cnt=0; 12 while(x)x-=(x&(-x)),cnt++; 13 return cnt; 14 } 15 void work(){ 16 int n,least,l,tot; 17 memset(can,0,sizeof(can)); 18 memset(f,0,sizeof(f)); 19 scanf("%d%d",&n,&least); 20 tot=(1<<n)-1; 21 for(int i=1;i<=n;i++) 22 scanf("%s",s[i]+1); 23 l=strlen(s[1]+1); 24 for(int i=1;i<=l;i++) 25 for(int j=0;j<=25;j++) 26 for(int k=1;k<=n;k++) 27 if(s[k][i]=='?' || s[k][i]==j+'a') 28 can[i][j]+=(1<<(k-1)); 29 f[0][tot]=1; 30 for(int i=0;i<l;i++){ 31 for(int j=0;j<=tot;j++){ 32 if(!f[i][j])continue; 33 for(int k=0;k<=25;k++){ 34 f[i+1][can[i+1][k]&j]+=f[i][j]; 35 f[i+1][can[i+1][k]&j]%=mod; 36 } 37 } 38 } 39 long long ans=0; 40 for(int i=0;i<=tot;i++){ 41 if(count(i)==least)ans+=f[l][i],ans%=mod; 42 } 43 printf("%lld\n",ans); 44 } 45 int main() 46 { 47 int T;scanf("%d",&T); 48 while(T--)work(); 49 return 0; 50 }