#include<cstdio>
#include<cstring>
const int mod=1000003;
int i, j, n, k, K, len, po[20];
int fit[30][60], f[60][40000];
char c[20][60];
inline int read(){
int t=getchar(), p=0;
while(t<'0'||t>'9') t=getchar();
while(t>='0'&&t<='9') p=p*10+t-48, t=getchar();
return p;
}
int check(int x){
int ans=0;
while(x){
if(x&1) ans++;
x>>=1;
}
return ans;
}
int main(){
freopen("set.in","r",stdin);
freopen("set.out","w",stdout);
n=read(), K=read();
for(po[0]=1,i=1;i<=n;i++) po[i]=po[i-1]*2;
for(i=1;i<=n;i++) scanf("%s", c[i]+1);
len=strlen(c[1]+1);
for(i=1;i<=len;i++) for(j=1;j<=n;j++) for(k=1;k<=26;k++)
if(c[j][i]=='?'||c[j][i]==k+96) fit[i][k]|=po[j-1];
int all=po[n]-1;
f[1][all]=1;
for(i=1;i<=len;i++) for(j=0;j<=all;j++) for(k=1;k<=26;k++){
int x=j&fit[i][k];
f[i+1][x]+=f[i][j];
if(f[i+1][x]>=mod) f[i+1][x]-=mod;
}
int ans=0;
for(i=0;i<=all;i++){
if(check(i)==K) ans+=f[len+1][i];
if(ans>=mod) ans-=mod;
}
printf("%d\n", ans);
fclose(stdin);
fclose(stdout);
return 0;
}
思路:状态压缩dp
用二进制枚举每一列的状态,然后按位与得到下一列的对应状态进行转移