Description
Data Constraint
Solution
以前做过一道经典题目和这题类似:铺砖块
很明显就是一道状压DP题目,把图形旋转成N*4的矩阵,复杂度显然就是
O(N∗24)
,但是发现N很大,那么就要用矩阵乘法了。在普通状压中,我们会处理出一个
24∗24
的二维数组,该数组表示从i状态能否转移到j状态,能为1,不能为0,这个矩阵就是转移矩阵,然后快速幂解决。
Code
var
f:array[0..40,0..16,0..16] of int64;
c:array[0..40] of longint;
a,z:array[0..16] of int64;
n,m,i,j,k,s:longint;
sum:int64;
function pd(x:longint):boolean;
var sum:longint;
begin
sum:=0;
while x>0 do
begin
if x mod 2=0 then
begin
if sum mod 2=1 then exit(false);
sum:=0;
end else inc(sum);
x:=x div 2;
end;
if sum mod 2=1 then exit(false) else exit(true);
end;
procedure doit;
var i,j,k:longint;
begin
s:=1;c[1]:=1;sum:=1;
while sum*2<=n do
begin
sum:=sum*2;
inc(s);
fillchar(f[s],sizeof(f[s]),0);
c[s]:=c[s-1]*2;
for i:=0 to 15 do
for j:=0 to 15 do
for k:=0 to 15 do
f[s,i,j]:=(f[s,i,j]+f[s-1,i,k]*f[s-1,k,j] mod m)mod m;
end;
end;
procedure deal(x:longint);
var i,j,k:longint;
begin
for i:=0 to 15 do if pd(i) then a[i]:=1 else a[i]:=0;
dec(x);
i:=s;
while x>0 do
begin
while c[i]>x do dec(i);
fillchar(z,sizeof(z),0);
for j:=0 to 15 do
for k:=0 to 15 do
z[j]:=(z[j]+a[k]*f[i,k,j])mod m;
a:=z;
x:=x-c[i];
end;
end;
begin
for i:=0 to 15 do
for j:=0 to 15 do
if pd(i+j) and((i and j)=0) then f[0,i,j]:=1;
readln(n,m);
while m<>0 do
begin
f[1]:=f[0];
doit;
deal(n);
writeln(a[0]);
readln(n,m);
end;
end.