题意:要求把2*n的方格分成k个连通区域,每个区域至少有一个格子。问你方案数模100000007之后是多少。
题解:一个比较神奇的dp,设
f[i,j,0/1]
,表示当前做到第i行,分成k个连通区域,第i行的两个格子属于/不属于同一个连通区域,
然后要分类讨论一下:
首先是
f[i,j,0]
的转移:
有如下几种情况:
由
f[i−1,j−1,1]
转移过来
由
f[i−1,j−1,1]
转移过来。
由
f[i−1,j−2,1]
转移过来。
由
f[i−1,j,0]
转移过来。
由
f[i−1,j−1,0]
转移过来。
由
f[i−1,k−1,0]
转移过来。
由
f[i−1,j−2,0]
转移过来。
所以
f[i,j,0]:=(f[i−1,j−1,1]∗2+f[i−1,j−2,1]+f[i−1,j,0]+f[i−1,j−1,0]∗2+f[i−1,j−2,0])
然后
f[i,j,1]
的转移类似,自己想一想吧。
贴上代码
const
maxn=1005;
mo=100000007;
var
f:array[0..maxn,-1..2*maxn,0..1] of int64;
i,j,n,k:longint;
begin
readln(n,k);
f[1,1,1]:=1;
f[1,2,0]:=1;
for i:=2 to n do
begin
for j:=1 to k do
begin
f[i,j,0]:=(f[i-1,j-1,1]*2+f[i-1,j-2,1]+f[i-1,j,0]+f[i-1,j-1,0]*2+f[i-1,j-2,0]) mod mo;
f[i,j,1]:=(f[i-1,j,0]*2+f[i-1,j,1]+f[i-1,j-1,1]+f[i-1,j-1,0]) mod mo;
end;
end;
writeln((f[n,k,0]+f[n,k,1]) mod mo);
write(#26);//注明:jzoj上数据有问题,要加这个,若不在jzoj上提交,可去掉此语句。
end.
the end
由于我的水平有限,难免会有些写错的地方,希望大家批评指正,多多包容,thank you for your patience.