原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1626.html

题目传送门 - 51Nod1626

题意

题解

  首先考虑形象的想象本题中的思维空间。我们把整个 2*2*3*n 的四维空间看作 n 个 2*2*3 的三维空间顺次排列。考虑到 1*1*1*2 的方块,我们如果把边长 2 放在第 4 维上,相当于是填充了连续两个三维空间的对应位置。否则,边长 1 就放在了第 4 维上,相当于在一个三维空间中填充 1*1*2 的方块。

  然后我们考虑状压 DP 。状态压缩当前三维空间的被填充状态。显然有 $2^{2\times 2\times 3}=4096$ 种情况。然后,我们考虑通过旋转、对称删除一些重复的状态,通过黑白染色删除一些没用的状态,最后剩下的状态数很少了。然后矩阵快速幂即可。

  如果要更加具体地了解如何删除状态,参见代码或者原题的题解。

代码

#include <bits/stdc++.h>
#define Hash(a,b,c) Ha[a][b][c]
using namespace std;
typedef long long LL;
const int N=105,mod=1e9+7;
LL n;
int t=0,a[N],Min[1<<12],ID[1<<12],Ha[5][5][5];
struct Mat{
int v[N][N];
Mat(){}
Mat(int x){
memset(v,0,sizeof v);
for (int i=1;i<=t;i++)
v[i][i]=x;
}
}M(0);
Mat operator * (Mat A,Mat B){
Mat C(0);
for (int i=1;i<=t;i++)
for (int j=1;j<=t;j++)
for (int k=1;k<=t;k++)
C.v[i][j]=(1LL*A.v[i][k]*B.v[k][j]+C.v[i][j])%mod;
return C;
}
Mat Pow(Mat x,LL y){
Mat ans(1);
for (;y;y>>=1,x=x*x)
if (y&1LL)
ans=ans*x;
return ans;
}
void SwapD(int &v,int i,int j){
if (((v>>i)^(v>>j))&1)
v^=(1<<i)^(1<<j);
}
int checkWB(int s){
int ans=0;
for (int i=1;i<=2;i++)
for (int j=1;j<=2;j++)
for (int k=1;k<=3;k++)
if (s>>Hash(i,j,k)&1)
if ((i+j+k)&1)
ans++;
else
ans--;
return ans==0;
}
int calc(int s){
int res=s;
for (int t=0;t<4;t++){
int v=s;
if (t&1)
for (int j=1;j<=2;j++)
for (int k=1;k<=3;k++)
SwapD(v,Hash(1,j,k),Hash(2,j,k));
if (t>>1)
for (int i=1;i<=2;i++)
for (int j=1;j<=2;j++)
SwapD(v,Hash(i,j,1),Hash(i,j,3));
for (int d=0;d<4;d++,res=min(res,v))
for (int i=1;i<=3;i++){
SwapD(v,Hash(1,1,i),Hash(1,2,i));
SwapD(v,Hash(1,2,i),Hash(2,2,i));
SwapD(v,Hash(2,2,i),Hash(2,1,i));
}
}
return res;
}
int dx[6]={ 0, 0, 0, 0, 1,-1},_x[6];
int dy[6]={ 0, 0, 1,-1, 0, 0},_y[6];
int dz[6]={ 1,-1, 0, 0, 0, 0},_z[6];
void GetXYZ(){
int cnt=0;
for (int i=1;i<=2;i++)
for (int j=1;j<=2;j++)
for (int k=1;k<=3;k++)
if ((i+j+k)&1)
cnt++,_x[cnt]=i,_y[cnt]=j,_z[cnt]=k;
}
void GetM(int S,int v,int t){
if (t>6){
M.v[S][ID[Min[v]]]++;
return;
}
GetM(S,v,t+1);
int x=_x[t],y=_y[t],z=_z[t],xx,yy,zz;
if (v>>Hash(x,y,z)&1)
return;
for (int i=0;i<6;i++){
xx=x+dx[i],yy=y+dy[i],zz=z+dz[i];
if ((1<=xx&&xx<=2&&1<=yy&&yy<=2&&1<=zz&&zz<=3)&&(~v>>Hash(xx,yy,zz)&1))
GetM(S,v^(1<<Hash(x,y,z))^(1<<Hash(xx,yy,zz)),t+1);
}
}
int main(){
int sz=1<<12;
for (int i=1;i<=2;i++)
for (int j=1;j<=2;j++)
for (int k=1;k<=3;k++)
Ha[i][j][k]=(i-1)*6+(j-1)*3+k-1;
for (int i=0;i<sz;i++)
if (checkWB(i))
if ((Min[i]=calc(i))==i)
a[++t]=i,ID[i]=t;
GetXYZ();
for (int i=1;i<=t;i++)
GetM(i,a[i]^(sz-1),1);
scanf("%lld",&n);
M=Pow(M,n);
printf("%d",M.v[ID[Min[sz-1]]][ID[Min[sz-1]]]);
return 0;
}

  

51Nod1626 B君的梦境 状压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. 【bzoj2004】[Hnoi2010]Bus 公交线路 状压dp+矩阵乘法

    题目描述 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决定按下述规则设计 ...

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

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

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

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

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

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

  7. nyoj1273 河南省第九届省赛_"宣传墙"、状压DP+矩阵幂加速

    宣传墙 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 ALPHA 小镇风景美丽,道路整齐,干净,到此旅游的游客特别多.CBA 镇长准备在一条道路南 面 4*N 的墙上做 ...

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

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

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

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

随机推荐

  1. 新建项目虚拟环境及pycharm配置

    基本操作 查询已有的虚拟环境 workon 激活虚拟环境 workon 虚拟环境名 退出虚拟环境 deactivate 删除虚拟环境 rmvirtualenv 虚拟环境名 查看python版本检查 p ...

  2. 第一篇----mysql体系

    mysql体系: 解释: 调用: 1.connectors:连接器 (远程调用mysql,Native很常用的mysql远程连接工具.其它是可以调用mysql支持的一些语言和方法) mysql结构 2 ...

  3. 你的B计划在哪里?

    春节同学聚会,大家聊起近况. 甲在实体经济部门工作,企业效益不好,正酝酿减员增效,他忧心忡忡,跳槽都不知道怎么跳,因为全行业都不景气. 乙从事互联网工作,行业发展热火朝天,新事物层出不穷,但是他已人到 ...

  4. vi快速查找

    用vim时,想高亮显示一个单词并查找的方发,将光标移动到所找单词. 1: shift + "*"  向下查找并高亮显示 2: shift + "#"  向上查找 ...

  5. 【进阶3-4期】深度解析bind原理、使用场景及模拟实现(转)

    这是我在公众号(高级前端进阶)看到的文章,现在做笔记  https://github.com/yygmind/blog/issues/23 bind() bind() 方法会创建一个新函数,当这个新函 ...

  6. swiper轮播图(逆向自动切换类似于无限循环)

    swiper插件轮播图,默认的轮播循序是会从右向左,第一张,第二张,第三张,然后肉眼可见是的从第三张从左到右倒回第一张,这样就会有些视觉体验不高, ,不过还是能够用swiper本身的特性更改成无限循环 ...

  7. C语言学习及应用笔记之二:C语言static关键字及其使用

    C语言有很多关键字,大多关键字使用起来是很明确的,但有一些关键字却要相对复杂一些.我们这里要说明的static关键字就是如此,它的功能很强大,相应的使用也就更复杂. 一般来说static关键字的常见用 ...

  8. log4j 知识点

    什么是log4j? log4j 是一个帮助程序员将日志语句输出到各种输出目标的工具. log4j 包的设计使得日志语句可以保留在已发布的代码中,而不会产生高性能成本. log4j 使用分层记录器可以有 ...

  9. Oracle Database 11g : SQL 基础

    简介 1:课程目标 2:课程 目标 3:Oracle Database 11g 以及相关产品概览 1:Oracle Database 11g :重点领域 2:Oracle Fusion Middlew ...

  10. SpringBoot集成多数据源

    多数据源就是连接多个数据库 1.在application.properties中配置两个数据库 spring.datasource.driverClassName=com.mysql.jdbc.Dri ...