瓷砖铺放 (状压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~\)的矩阵给出了 ...
随机推荐
- Java 集合系列 05 Vector详细介绍(源码解析)和使用示例
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- MATLAB 随机生成互不重叠的多个矩形
建立m文件draw_rectangle.m. 其中p生成矩形的个数 function draw_rectangle(p) t = 1; x = rand(1)*10; y = rand(1)*10; ...
- 445. Add Two Numbers II ——while s1 or s2 or carry 题目再简单也要些测试用例
You are given two linked lists representing two non-negative numbers. The most significant digit com ...
- [转]开发者需要了解的WebKit(mark)
以下内容转自:http://www.infoq.com/cn/articles/webkit-for-developers -------------------------------------- ...
- linux 安装 apache
1. 系统基本信息 CentOS 6.4 内存2G 硬盘 200G cpu 4核 (cat /proc/cpuinfo |grep 'processor'|wc -l 查看cpu核数 ...
- js中Array自定义contains, indexOf, delete方法.
Array.prototype.contains = function (elem) { for (var i = 0; i < this.length; i++) { if (this[i] ...
- [示例]NSPredicate基础-查询数组中负荷条件的子集
代码: #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepo ...
- 【bzoj3160】万径人踪灭
题意:给一个只含a.b的字符串,求所有的回文不连续子序列. manacher+FFT. 先求出所有回文序列,再减去连续子序列(即回文串). 将a.b分开考虑,对于一个对称轴,以其为回文中心的回文序列的 ...
- HTML5表单新增属性
1.form 原来html里面,表单里的元素应该包裹在表单里,如 <form action="login.php" method="get"> &l ...
- myeclipse9.x,10.x 安装时出现pulse-one-64,failed to load the JNI shared library