由于方块最多涉及3行,于是考虑将每两行状压起来,dfs搜索每种状态之间的转移。

这样一共有2^12种状态,显然进行矩阵快速幂优化时会超时,便考虑减少状态。

进行两遍bfs,分别为初始状态可以到达的状态,和可以到达终止状态的状态。

同时出现在两次bfs中的状态即为有效状态,一共有141种。

这样就可以跑出来了。

未加矩阵快速幂 50分

 const dx:array[..,..] of longint=
((-,,),(-,,),(,,),(,,),(-,,),(-,,),(,,),(-,,));
dy:array[..,..] of longint=
((,,),(,-,),(,-,),(,,),(,,-),(,,-),(,,-),(,,));
mo=;
var n,m,lx,i,j,k:longint;
a:array[..,..] of longint;
g:array[..,..] of longint;
dp:array[..,..] of longint;
function ok(x,y:longint):boolean; inline;
begin
if (x>=) and (x<=) and (y>=) and (y<=m) and (a[x,y]=) then exit(true);
exit(false);
end;
function check(y,j:longint):boolean;
var i,x:longint;
begin
x:=;
if not ok(x,y) then exit(false);
for i:= to do
if not ok(x+dx[j,i],y+dy[j,i]) then exit(false);
exit(true);
end;
procedure fill(y,j,cl:longint);
var i,x:longint;
begin
x:=;
a[x,y]:=cl;
for i:= to do
a[x+dx[j,i],y+dy[j,i]]:=cl;
end;
procedure dfs(x,lt:longint);
var i,j,sum:longint;
begin
if x=m+ then
begin
for i:= to m do if a[,i]= then exit; //保证了DP的正确性
sum:=;
for i:= to do
for j:= to m do
sum:=sum*+a[i,j];
inc(g[lt][sum]);
exit;
end;
dfs(x+,lt);
for i:= to do
if check(x,i) then
begin
fill(x,i,);
dfs(x+,lt);
fill(x,i,);
end;
end;
begin
assign(input,'tile.in');reset(input);
assign(output,'tile.out');rewrite(output);
readln(n,m);
for i:= to <<(*m)- do
begin
for j:= to m do
if i and (<<(m*-j))> then a[,j]:= else a[,j]:=;
for j:= to m do
if i and (<<(m-j))> then a[,j]:= else a[,j]:=;
dfs(,i);
end;
dp[][(<<m-)<<m]:=;
for i:= to n+ do
for j:= to <<(*m)- do
for k:= to <<(*m)- do
dp[i][j]:=(dp[i][j]+dp[i-][k]*g[k][j]) mod mo;
writeln(dp[n+][(<<m-)<<m]);
close(input);
close(output);
end.

AC 代码1:

 const dx:array[..,..] of longint=
((-,,),(-,,),(,,),(,,),(-,,),(-,,),(,,),(-,,));
dy:array[..,..] of longint=
((,,),(,-,),(,-,),(,,),(,,-),(,,-),(,,-),(,,));
mo=;
type arr=array[..,..] of int64;
var i,j,k,m,xh:longint;
n:int64;
a:array[..,..] of longint;
g:array[..,..] of longint;
b:array[..] of longint;
v1,v2:array[..] of boolean;
pos:array[..] of int64;
mat,f:arr;
function ok(x,y:longint):boolean; inline;
begin
if (y>=) and (y<=m) and (a[x,y]=) then exit(true);
exit(false);
end;
function check(y,j:longint):boolean; inline;
var i,x:longint;
begin
x:=;
if not ok(x,y) then exit(false);
for i:= to do
if not ok(x+dx[j,i],y+dy[j,i]) then exit(false);
exit(true);
end;
procedure fill(y,j,cl:longint); inline;
var i,x:longint;
begin
x:=;
a[x,y]:=cl;
for i:= to do
a[x+dx[j,i],y+dy[j,i]]:=cl;
end;
procedure dfs(x,lt:longint);
var i,j,sum:longint;
begin
if x=m+ then
begin
for i:= to m do if a[,i]= then exit;
sum:=;
for i:= to do
for j:= to m do
sum:=sum*+a[i,j];
inc(g[lt][sum]);
exit;
end;
dfs(x+,lt);
for i:= to do
if check(x,i) then
begin
fill(x,i,);
dfs(x+,lt);
fill(x,i,);
end;
end;
procedure bfs;
var i,j,l,r,x,y:longint;
begin
fillchar(v1,sizeof(v1),false);
fillchar(v2,sizeof(v2),false);
l:=; r:=; b[]:=(<<m-)<<m; v1[(<<m-)<<m]:=true;
while l<=r do
begin
x:=b[l];
for y:= to (<<(m*)-) do
if (g[x,y]>) and not v1[y] then
begin
v1[y]:=true;
inc(r);
b[r]:=y;
end;
inc(l);
end;
l:=; r:=; b[]:=(<<m-)<<m; v2[(<<m-)<<m]:=true;
while l<=r do
begin
x:=b[l];
for y:= to <<(m*)- do
if (g[y,x]>) and not v2[y] then
begin
v2[y]:=true;
inc(r);
b[r]:=y;
end;
inc(l);
end;
xh:=;
for i:= to <<(m*)- do
if v1[i] and v2[i] then
begin
inc(xh);
pos[i]:=xh;
end;
for i:= to r do
for j:= to r do
mat[pos[b[i]],pos[b[j]]]:=g[b[i],b[j]];
end;
operator *(a,b:arr) c:arr; inline;
var i,j,k:longint;
begin
for i:= to xh do
for j:= to xh do
begin
c[i,j]:=;
for k:= to xh do
c[i,j]:=(c[i,j]+a[i,k]*b[k,j]);
c[i,j]:=c[i,j] mod mo;
end;
exit(c);
end;
begin
assign(input,'tile.in');reset(input);
assign(output,'tile.out');rewrite(output);
readln(n,m);
for i:= to <<(*m)- do
begin
for j:= to m do
if i and (<<(m*-j))> then a[,j]:= else a[,j]:=;
for j:= to m do
if i and (<<(m-j))> then a[,j]:= else a[,j]:=;
dfs(,i);
end;
{dp[1][(1<<m-1)<<m]:=1;
for i:=2 to n+1 do
for j:=0 to 1<<(2*m)-1 do
for k:=0 to 1<<(2*m)-1 do
dp[i][j]:=(dp[i][j]+dp[i-1][k]*g[k][j]) mod mo;}
bfs;
for i:= to xh do f[i,i]:=;
writeln(xh);
while n> do
begin
if n and = then f:=f*mat;
mat:=mat*mat;
n:=n>>;
end;
writeln(f[pos[(<<m-)<<m]][pos[(<<m-)<<m]]);
close(input);
close(output);
end.

AC 代码2 :(Orz rpCardinal)

 #include <cstdio>
#include <cstring>
#define P 65521 #ifdef _WIN32
#define ll "%I64d"
#else
#define ll "%lld"
#endif int m,M,ST,N,q[],h[],pos[];
long long n,g[][],t[][];
bool b[][],v1[],v2[]; struct matrix
{
long long a[][];
matrix() {memset(a,,sizeof(a));}
void one() {for (int i=;i<=N;++i) a[i][i]=;}
matrix& operator*=(const matrix &B)
{
memset(t,,sizeof(t));
for (int i=;i<=N;++i)
for (int j=;j<=N;++j)
for (int k=;k<=N;++k)
t[i][j]=(t[i][j]+a[i][k]*B.a[k][j])%P;
memcpy(a,t,sizeof(a)); return *this;
}
}A,R; bool can(int i,int j)
{return i>=&&i<&&j>=&&j<m&&!b[i][j];} bool check(int k,int i)
{
switch (k)
{
case :return can(,i)&&can(,i+)&&can(,i);
case :return can(,i)&&can(,i+)&&can(,i);
case :return can(,i)&&can(,i-)&&can(,i);
case :return can(,i)&&can(,i-)&&can(,i);
case :return can(,i)&&can(,i)&&can(,i)&&can(,i+);
case :return can(,i)&&can(,i)&&can(,i-)&&can(,i+);
case :return can(,i)&&can(,i)&&can(,i)&&can(,i-);
case :return can(,i)&&can(,i)&&can(,i-)&&can(,i+);
default:return ;
}
} bool fill(int k,int i,int v)
{
switch (k)
{
case :return b[][i]=b[][i+]=b[][i]=v;
case :return b[][i]=b[][i+]=b[][i]=v;
case :return b[][i]=b[][i-]=b[][i]=v;
case :return b[][i]=b[][i-]=b[][i]=v;
case :return b[][i]=b[][i]=b[][i]=b[][i+]=v;
case :return b[][i]=b[][i]=b[][i-]=b[][i+]=v;
case :return b[][i]=b[][i]=b[][i]=b[][i-]=v;
case :return b[][i]=b[][i]=b[][i-]=b[][i+]=v;
default:return ;
}
} void dfs(int dep,int last)
{
if (dep>m)
{
for (int i=;i<m;++i) if (!b[][i]) return;
int next=;
for (int i=;i;--i)
for (int j=m-;j>=;--j)
next=next*+b[i][j];
++g[last][next]; return;
}
dfs(dep+,last);
for (int i=;i<=;++i)
if (check(i,dep))
{fill(i,dep,); dfs(dep+,last); fill(i,dep,);}
} void bfs()
{
int l=,r=; q[++r]=ST; v1[ST]=;
while (l<r)
{
int x=q[++l];
for (int y=;y<M;++y)
if (g[x][y]&&!v1[y]) {v1[y]=; q[++r]=y;}
}
l=r=; q[++r]=ST; v2[ST]=;
while (l<r)
{
int x=q[++l];
for (int y=;y<M;++y)
if (g[y][x]&&!v2[y]) {v2[y]=; q[++r]=y;}
}
for (int i=;i<M;++i)
if (v1[i]&&v2[i]) {h[++N]=i; pos[i]=N;}
for (int i=;i<M;++i)
for (int j=;j<M;++j)
A.a[pos[i]][pos[j]]=g[i][j];
} void pow(long long b)
{while (b) {if (b&) R*=A; A*=A; b>>=;}} int main()
{
freopen("tile.in","r",stdin);
freopen("tile.out","w",stdout);
scanf(ll "%d",&n,&m); M=<<(*m); ST=(<<m)-;
for (int st=;st<M;++st)
{
for (int i=;i<m;++i) b[][i]=(st>>i)&;
for (int i=;i<m;++i) b[][i]=(st>>(i+m))&;
dfs(,st);
}
bfs(); R.one(); pow(n);
printf(ll "\n",R.a[pos[ST]][pos[ST]]);
fclose(stdin); fclose(stdout);
return ;
}

瓷砖铺放 (状压DP+矩阵快速幂)的更多相关文章

  1. HDU 5434 Peace small elephant 状压dp+矩阵快速幂

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant  Accepts: 38  Submissions: ...

  2. 【BZOJ】2004: [Hnoi2010]Bus 公交线路 状压DP+矩阵快速幂

    [题意]n个点等距排列在长度为n-1的直线上,初始点1~k都有一辆公车,每辆公车都需要一些停靠点,每个点至多只能被一辆公车停靠,且每辆公车相邻两个停靠点的距离至多为p,所有公车最后会停在n-k+1~n ...

  3. BZOJ 4000: [TJOI2015]棋盘( 状压dp + 矩阵快速幂 )

    状压dp, 然后转移都是一样的, 矩阵乘法+快速幂就行啦. O(logN*2^(3m)) ------------------------------------------------------- ...

  4. 【XSY2524】唯一神 状压DP 矩阵快速幂 FFT

    题目大意 给你一个网格,每个格子有概率是\(1\)或是\(0\).告诉你每个点是\(0\)的概率,求\(1\)的连通块个数\(\bmod d=0\)的概率. 最开始所有格子的概率相等.有\(q\)次修 ...

  5. 2018.09.28 hdu5434 Peace small elephant(状压dp+矩阵快速幂)

    传送门 看到n的范围的时候吓了一跳,然后发现可以矩阵快速幂优化. 我们用类似于状压dp的方法构造(1(1(1<<m)∗(1m)*(1m)∗(1<<m)m)m)大小的矩阵. 然后 ...

  6. BZOJ 2004 公交线路(状压DP+矩阵快速幂)

    注意到每个路线相邻车站的距离不超过K,也就是说我们可以对连续K个车站的状态进行状压. 然后状压DP一下,用矩阵快速幂加速运算即可. #include <stdio.h> #include ...

  7. [BZOJ4000][TJOI2015]棋盘(状压DP+矩阵快速幂)

    题意极其有毒,注意给的行列都是从0开始的. 状压DP,f[i][S]表示第i行状态为S的方案数,枚举上一行的状态转移.$O(n2^{2m})$ 使用矩阵加速,先构造矩阵a[S1][S2]表示上一行为S ...

  8. BZOJ2004 HNOI2010公交线路(状压dp+矩阵快速幂)

    由数据范围容易想到矩阵快速幂和状压. 显然若要满足一辆公交车的相邻站台差不超过p,则每相邻p个站台中每辆车至少经过一个站台.可以发现这既是必要的,也是充分的. 开始的时候所有车是相邻的.考虑每次把一辆 ...

  9. 【BZOJ4000】【LOJ2104】【TJOI2015】棋盘 (状压dp + 矩阵快速幂)

    Description ​ 有一个\(~n~\)行\(~m~\)列的棋盘,棋盘上可以放很多棋子,每个棋子的攻击范围有\(~3~\)行\(~p~\)列.用一个\(~3 \times p~\)的矩阵给出了 ...

随机推荐

  1. MySQL索引实现

    摘自:http://blog.codinglabs.org/articles/theory-of-mysql-index.html 在MySQL中,索引属于存储引擎级别的概念,不同存储引擎对索引的实现 ...

  2. Windows Store App 应用程序安装目录

    前面介绍了如何对本地应用存储空间中的文件以及文件夹进行操作,在应用中除了可以对本地应用存储空间进行操作之外,还可以对应用程序安装目录进行相关操作.本节将通过一个示例,详细讲解如何对应用程序安装目录中的 ...

  3. hadoop工作流引擎之azkaban [转]

    介绍 Azkaban是twitter出的一个任务调度系统,操作比Oozie要简单很多而且非常直观,提供的功能比较简单.Azkaban以Flow为执行单元进行定时调度,Flow就是预定义好的由一个或多个 ...

  4. spring中配置jdbc数据源

    1.加入jdbc驱动器包,mysql-connector-java.jar 2.加入commons-dbcp.jar配置数据源 3.在classpath下新建文件jdbc.properties,配置j ...

  5. java面向对象编程--第十一章 异常处理

    1.异常:描述出错信息的对象. 字节码校验时,如发生错误,则会抛出异常. 2.所有异常的父类是Exception,异常可以捕获,可以处理. 所有错误的父类是Error,错误可以捕获,但不能处理. Th ...

  6. HBase vs. BigTable Comparison - HBase对比BigTable

    HBase vs. BigTable Comparison HBase is an open-source implementation of the Google BigTable architec ...

  7. sql类型转换

    CAST 和 CONVERT 将某种数据类型的表达式显式转换为另一种数据类型.CAST 和 CONVERT 提供相似的功能. 语法 使用 CAST: CAST ( expression AS data ...

  8. HTML5表单新增属性

    1.form 原来html里面,表单里的元素应该包裹在表单里,如 <form action="login.php" method="get"> &l ...

  9. POJ 1083 Moving Tables 思路 难度:0

    http://poj.org/problem?id=1083 这道题题意是有若干段线段,每次要求线段不重叠地取,问最少取多少次. 因为这些线段都是必须取的,所以需要让空隙最小 思路: 循环直到线段全部 ...

  10. HDU 4046 Panda

    线段树单点更新,要注意两段合并多出的答案的计算即可 //======================================================================== ...