还是那句话s<=10 必然想到状压
题目唯一的难点在于怎么转移整除
整除即是mod d=0,我们用f[cur,j]表示选取状况为cur,余数为j的方案数
注意一个数a1a2a3…an (ai表示第i位的数字)
这个数可以这样表示[(a1*10+a2)*10+a3]*10……
根据mod的运算律,所以转移就很明显了吧
注意这里算出的方案数没有考虑几个数字重复的情况
所以还要用可重复排列的技术方法除一下
1 var f:array[0..1100,0..1100] of longint; 2 s,a,d:array[0..20] of longint; 3 ans,p,x,i,j,k,m,n,t,tot:longint; 4 ch:char; 5 6 begin 7 readln(tot); 8 d[0]:=1; 9 for i:=1 to 10 do 10 d[i]:=d[i-1]*i; 11 while tot>0 do 12 begin 13 dec(tot); 14 fillchar(s,sizeof(s),0); 15 t:=0; 16 read(ch); 17 while ch<>' ' do 18 begin 19 x:=ord(ch)-48; 20 inc(t); 21 a[t]:=x; 22 inc(s[x]); 23 read(ch); 24 end; 25 readln(p); 26 fillchar(f,sizeof(f),0); 27 m:=1 shl t-1; 28 f[0,0]:=1; 29 for i:=0 to m do 30 for j:=0 to p-1 do 31 for k:=0 to t-1 do 32 begin 33 x:=1 shl k; 34 if i and x=0 then 35 inc(f[i or x,(j*10+a[k+1]) mod p],f[i,j]); 36 end; 37 38 ans:=f[m,0]; 39 for i:=0 to 9 do 40 ans:=ans div d[s[i]]; 41 writeln(ans); 42 end; 43 end.