bzoj3294

感觉自己就是不怎么擅长计数的问题

设f[k,i,j]表示前k种颜色占据了i行j列的方案

g[k,i,j]表示第k种颜色占据了i行j列的方案,注意要减去并没占据满i行j列的情况

然后转移就很好写了

像这种题目构造好了状态后都非常好解决

 1 const mo=1000000009;
 2 var g,f:array[0..11,0..31,0..31] of longint;
 3     c:array[0..1010,0..1010] of longint;
 4     a:array[0..15] of longint;
 5     n,m,i,j,k,q,x,y,ans:longint;
 6 
 7 begin
 8   readln(n,m,q);
 9   c[0,0]:=1;
10   for i:=1 to n*m do
11   begin
12     c[i,0]:=1;
13     for j:=1 to i do
14       c[i,j]:=(c[i-1,j]+c[i-1,j-1]) mod mo;
15   end;
16   for i:=1 to q do
17     read(a[i]);
18   for k:=1 to q do
19     for i:=1 to n do
20       for j:=1 to m do
21       begin
22         if (i*j<a[k]) or (i>a[k]) or (j>a[k]) then continue;
23         g[k,i,j]:=c[i*j,a[k]];
24         for x:=1 to i do
25           for y:=1 to j do
26             if (i-x+j-y)>0 then
27               g[k,i,j]:=(g[k,i,j]-int64(g[k,x,y])*int64(c[i,x]) mod mo*int64(c[j,y]) mod mo+mo) mod mo;
28       end;
29 
30   f[0,0,0]:=1;
31   for k:=1 to q do
32   begin
33     a[k]:=a[k]+a[k-1];
34     for i:=1 to n do
35       for j:=1 to m do
36       begin
37         if i*j<a[k] then continue;
38         for x:=1 to i do
39           for y:=1 to j do
40             f[k,i,j]:=(f[k,i,j]+int64(f[k-1,i-x,j-y])*int64(g[k,x,y]) mod mo*int64(c[i,x]) mod mo*int64(c[j,y]) mod mo) mod mo;
41       end;
42   end;
43   for i:=1 to n do
44     for j:=1 to m do
45       ans:=(ans+int64(f[q,i,j])*int64(c[n,i]) mod mo*int64(c[m,j]) mod mo) mod mo;
46 
47   writeln(ans);
48 end.
View Code
原文地址:https://www.cnblogs.com/phile/p/4511814.html