瓷砖铺放 (状压DP+矩阵快速幂)
由于方块最多涉及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+矩阵快速幂)的更多相关文章
- HDU 5434 Peace small elephant 状压dp+矩阵快速幂
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant Accepts: 38 Submissions: ...
- 【BZOJ】2004: [Hnoi2010]Bus 公交线路 状压DP+矩阵快速幂
[题意]n个点等距排列在长度为n-1的直线上,初始点1~k都有一辆公车,每辆公车都需要一些停靠点,每个点至多只能被一辆公车停靠,且每辆公车相邻两个停靠点的距离至多为p,所有公车最后会停在n-k+1~n ...
- BZOJ 4000: [TJOI2015]棋盘( 状压dp + 矩阵快速幂 )
状压dp, 然后转移都是一样的, 矩阵乘法+快速幂就行啦. O(logN*2^(3m)) ------------------------------------------------------- ...
- 【XSY2524】唯一神 状压DP 矩阵快速幂 FFT
题目大意 给你一个网格,每个格子有概率是\(1\)或是\(0\).告诉你每个点是\(0\)的概率,求\(1\)的连通块个数\(\bmod d=0\)的概率. 最开始所有格子的概率相等.有\(q\)次修 ...
- 2018.09.28 hdu5434 Peace small elephant(状压dp+矩阵快速幂)
传送门 看到n的范围的时候吓了一跳,然后发现可以矩阵快速幂优化. 我们用类似于状压dp的方法构造(1(1(1<<m)∗(1m)*(1m)∗(1<<m)m)m)大小的矩阵. 然后 ...
- BZOJ 2004 公交线路(状压DP+矩阵快速幂)
注意到每个路线相邻车站的距离不超过K,也就是说我们可以对连续K个车站的状态进行状压. 然后状压DP一下,用矩阵快速幂加速运算即可. #include <stdio.h> #include ...
- [BZOJ4000][TJOI2015]棋盘(状压DP+矩阵快速幂)
题意极其有毒,注意给的行列都是从0开始的. 状压DP,f[i][S]表示第i行状态为S的方案数,枚举上一行的状态转移.$O(n2^{2m})$ 使用矩阵加速,先构造矩阵a[S1][S2]表示上一行为S ...
- BZOJ2004 HNOI2010公交线路(状压dp+矩阵快速幂)
由数据范围容易想到矩阵快速幂和状压. 显然若要满足一辆公交车的相邻站台差不超过p,则每相邻p个站台中每辆车至少经过一个站台.可以发现这既是必要的,也是充分的. 开始的时候所有车是相邻的.考虑每次把一辆 ...
- 【BZOJ4000】【LOJ2104】【TJOI2015】棋盘 (状压dp + 矩阵快速幂)
Description 有一个\(~n~\)行\(~m~\)列的棋盘,棋盘上可以放很多棋子,每个棋子的攻击范围有\(~3~\)行\(~p~\)列.用一个\(~3 \times p~\)的矩阵给出了 ...
随机推荐
- mouseleave 与 mouseout 的不同
Q:给某div添加mouseout事件后,在空白区域移动到其子元素(如按钮)上(此时并没有离开此div)时,会触发mouseout事件,而mouseleave则不会 A:与 mouseout 事件不同 ...
- HDU 2181 哈密顿绕行世界问题 dfs 难度:1
http://acm.hdu.edu.cn/showproblem.php?pid=2181 只有20个城市,而且每个点的度数恰好是3,也就意味着,对于即将进入环中的点,入度1,出度2,下一个点只有两 ...
- (DFS)hdoj1010-Tempter of the Bone
#include<cstdio> #include<cmath> #include<stdlib.h> ][]={{,},{,-},{,},{-,}},escape ...
- IT公司100题-15-求二元查找树的镜像
问题描述: 输入一颗二元查找树,将该树转换为它的镜像树,即对每一个节点,互换左右子树. 例如输入: 6/ \4 12/ \ / \2 5 8 16 输出: 6/ ...
- struts中的数据校验
1.struts中如何进行数据校验 在每一个Action类中,数据校验一般都写在业务方法中,比如login().register()等.struts提供了数据校验功能.每个继承自ActionSuppo ...
- 5个最顶级jQuery图表类库插件-Charting plugin
转载: http://www.cnblogs.com/chu888chu888/archive/2012/12/22/2828962.html 作者:Leonel Hilario翻译:Terry li ...
- redis2.8--内存管理
总而言之,redis内存管理是采用主要由操作系统自主控制内存分配,辅之以简单封装,达到简单且稍微改良的性能. 内存块,标记上本块size 如上图所示, 当调用zmalloc/zmalloc时,输入参数 ...
- Codeforces Round #326 (Div. 2)-Duff in Love
题意: 一个数x被定义为lovely number需要满足这样的条件:不存在一个数a(a>1),使得a的完全平方是x的因子(即x % a2 != 0). 给你一个数n,求出n的因子中为love ...
- 傅里叶变换:MP3、JPEG和Siri背后的数学
九年前,当我还坐在学校的物理数学课的课堂里时,我的老师为我们讲授了一种新方法,给我留下了深刻映像.我认为,毫不夸张地说,这是对数学理论发现最广泛的应用.应用的领域包括:量子物理.射电天文学.MP3和J ...
- android Xutils dbutils 注解
xUtils DbUtils 关于实体类注解 汇总 RockyZhang 发布于 1年前,共有 0 条评论 先来官方demo DbUtils db = DbUtils.create(this); ...