本题包含多组数据。
第一行:一个整数T,表示数据的个数。
对于每组数据:
第一行:两个整数,N 和K(含义如题目表述)。
接下来N 行:每行一个字符串。
输出格式:
对于每组数据,输出方案数目(共T 行)。
样例输入:
1
2 1
a?
?b
样例输出:
50
数据范围:
对于30%的数据,T ≤ 5,N ≤ 5,字符串长度≤ 20;
对于70%的数据,T ≤ 5,N ≤ 13,字符串长度≤ 30;
对于100%的数据,T ≤ 5,N ≤ 15,字符串长度≤ 50。
dp
用二进制表示匹配状态,枚举每位枚举字母进行对之前出现的状态进行转移
错误:模的数是1000003,打成了100003
program pset;
const
maxn=1000003;
var
ans,t,n,k,i,j,o,l,status,all,temp,q:longint;
loop:char;
s:array [0..15] of string[50];
tot:array [0..1] of longint;
f,dl:array [0..1,0..32768] of longint;
yes:array [0..32768] of boolean;
function calc (temp:longint):longint;
var
i,all:longint;
begin
all:=0;
for i:=1 to n do
if (1 shl (i-1)) and temp <> 0 then inc(all);
exit(all);
end;
begin
assign(input,'set.in');
reset(input);
assign(output,'set.out');
rewrite(output);
readln(t);
while t<>0 do
begin
readln(n,k);
for i:=1 to n do
readln(s[i]);
l:=length(s[i]);
o:=0;
fillchar(f[o],sizeof(f[o]),0);
f[o,(1 shl n) - 1]:=1;
tot[o]:=1;
dl[o,1]:=(1 shl n) - 1;
for i:=1 to l do
begin
o:=1-o;
fillchar(yes,sizeof(yes),false);
fillchar(f[o],sizeof(f[o]),0);
tot[o]:=0;
for loop:='a' to 'z' do
begin
status:=0;
all:=0;
for j:=1 to n do
if (s[j][i]=loop)or(s[j][i]='?') then
begin
inc(all);
status:=status+(1 shl (j-1));
end;
if all<k then continue;
for j:=1 to tot[1-o] do
if f[1-o,dl[1-o,j]]<>0 then
begin
temp:=status and dl[1-o,j];
if calc(temp)<k then continue;
if not yes[temp] then
begin
yes[temp]:=true;
inc(tot[o]);
dl[o,tot[o]]:=temp;
end;
f[o,temp]:=(f[o,temp]+f[1-o,dl[1-o,j]]) mod maxn;
end;
end;
end;
ans:=0;
for i:=1 to tot[o] do
if calc(dl[o,i])=k then ans:=(ans+f[o,dl[o,i]]) mod maxn;
writeln(ans);
dec(t);
end;
close(input);
close(output);
end.