状态压缩+矩阵乘法hdu-4332-Constructing Chimney
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4332
题目意思:
用1*1*2的长方体构造一个中间为空的底面3*3的立体烟囱。
解题思路:
实际上就是poj上这道题的升华版。推荐先做那道题。
只不过本题的每一层相当于poj上那题的每一行,此题层数很多,所以很直白的想到用矩阵快速幂加速。
这类型的矩阵乘法做的比较少。
用二维矩阵表示两层之间的转移关系,第一维表示上一层的状态,第二维表示下一层的状态,作为基矩阵。每次乘以它就相当于加了一层。状态图和矩阵转移如下,虽然很丑,但还看的清。
0表示当前层不放,那么它下面的一层肯定要为1(并且还是竖着的1),
1表示当前层放,可以是平着,也可以是竖着。(最后在统计最后一层平放的情况,最后一层竖着放肯定不行,超过了)
因为要多次调用基矩阵的偶次方,故预处理给保存起来。
代码:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#define eps 1e-6
#define INF 0x1f1f1f1f
#define PI acos(-1.0)
#define ll __int64
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std; /*
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
*/ #define Maxn 300
#define M 1000000007 struct Mar
{
int r,c;
ll sa[Maxn][Maxn]; void init(int a,int b) //矩阵的初始化
{
r=a,c=b;
memset(sa,0,sizeof(sa));
} };
Mar mar[35]; //mar[][i][j] 表示从当前层i状态转到下一层的j状态的种数
//这种矩阵构造还是第一次见
ll ans[Maxn],tmp[Maxn];
int m; Mar operator *(const Mar &a,const Mar &b)
{
Mar cc;
cc.init(a.r,b.c); for(int k=0;k<=a.c;k++) //注意要从0开始,因为0也是一种状态,纠结了好半天
{
for(int i=0;i<=a.r;i++)
{
if(a.sa[i][k]==0) //矩阵优化加速,把a矩阵的列或b矩阵的行 作为第一个循环
continue;
for(int j=0;j<=b.c;j++)
{
if(b.sa[k][j]==0)
continue;
cc.sa[i][j]=(cc.sa[i][j]+a.sa[i][k]*b.sa[k][j])%M;
}
}
}
return cc;
}
bool can[Maxn]; bool ok(int st) //是否有含有偶数个1 是的话可以横着放
{
if(st==0)
return true;
int i=0;
while((st&(1<<i))&&(i<8)) //找到第一个不是1的位置
i++;
if(i>=8)
return true;
for(int j=i+1;j<=i+8;j++) //循环起来,最多只需找8位
{
if(st&(1<<(j%8))) //两个两个一找
{
if(st&(1<<((j+1)%8)))
j++;
else
return false;
}
}
return true;
}
void iscan()
{
memset(can,false,sizeof(can));
for(int i=0;i<m;i++)
if(ok(i)) //有偶数个连续的1
can[i]=true;
return ;
} void Initba()
{//mar[0]应该是base mar[1]为base^2 mar[2]为base^4
mar[0].init(m-1,m-1);
for(int i=0;i<m;i++)
for(int j=0;j<m;j++)
{
if((i|j)==m-1&&can[i&j])
mar[0].sa[i][j]=1;
}
mar[0].sa[m-1][m-1]=2;// 此时下面一层可以有两种放法,题目中的第一个样例
for(int i=1;i<32;i++) //先预处理起来,因为每次都要计算矩阵的话,很慢
mar[i]=mar[i-1]*mar[i-1];
}
void mul(int x)
{
memset(tmp,0,sizeof(tmp));
for(int i=0;i<m;i++) //奇数的话 乘以一个
{
for(int j=0;j<m;j++)
tmp[i]=(ans[j]*mar[x].sa[j][i]+tmp[i])%M;
}
for(int i=0;i<m;i++)
ans[i]=tmp[i];
} void quick(int n)
{
memset(ans,0,sizeof(ans));
ans[m-1]=1; //表示第一层必须全为1才可能在上面放,1是一个标识,表示之前的0层的数量
n--; //第一层已经放好了
for(int i=0;n&&i<32;i++)
if(n&(1<<i))
mul(i);
} int main()
{
m=1<<8;
// printf("%d\n",m);
iscan();
Initba();
int n,t;
scanf("%d",&t);
for(int ca=1;ca<=t;ca++)
{
scanf("%d",&n);
quick(n);
ll sum=0;
for(int i=0;i<m;i++)
if(can[i]) //最后一层可以平铺
{
sum=(sum+ans[i])%M;
if(i==m-1) //最后一层有两种平铺法
sum=(sum+ans[i])%M;
}
printf("Case %d: %I64d\n",ca,sum);
}
return 0;
}
状态压缩+矩阵乘法hdu-4332-Constructing Chimney的更多相关文章
- luogu1357 花园 状态压缩 矩阵快速幂
题目大意 小L有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为1~N(2<=N<=10^15).他的环形花园每天都会换一个新花样,但他的花园都不外乎一个规则,任意相邻M(2<= ...
- 【状态压缩DP】HDU 4352 XHXJ'S LIS
题目大意 Vjudge链接 定义一个数的内部LIS长度表示这个数每个数位构成的序列的LIS长度,给出区间\([l,r]\),求区间内内部LIS长度为\(k\)的数的个数. 输入格式 第一行给出数据组数 ...
- 矩阵乘法 --- hdu 4920 : Matrix multiplication
Matrix multiplication Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/ ...
- 洛谷P1357 花园(状态压缩 + 矩阵快速幂加速递推)
题目链接:传送门 题目: 题目描述 小L有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为1~N(<=N<=^).他的环形花园每天都会换一个新花样,但他的花园都不外乎一个规则,任意相邻 ...
- HDU - 6185 :Covering(矩阵乘法&状态压缩)
Bob's school has a big playground, boys and girls always play games here after school. To protect bo ...
- HDU 5768 Lucky7 (容斥原理 + 中国剩余定理 + 状态压缩 + 带膜乘法)
题意:……应该不用我说了,看起来就很容斥原理,很中国剩余定理…… 方法:因为题目中的n最大是15,使用状态压缩可以将所有的组合都举出来,然后再拆开成数组,进行中国剩余定理的运算,中国剩余定理能够求出同 ...
- HDU 4921 Map DFS+状态压缩+乘法计数
算最多十条链,能截取某前缀段,每种方案都可以算出一个权值,每种方案的概率都是总数分之一,问最后能构成的所有可能方案数. 对计数原理不太敏感,知道是DFS先把链求出来,但是想怎么统计方案的时候想了好久, ...
- HDU 5607 graph(DP+矩阵乘法)
[题目链接] http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=663&pid=1002 [题意] 给定一个有向 ...
- HDU 3681 Prison Break(状态压缩dp + BFS)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3681 前些天花时间看到的题目,但写出不来,弱弱的放弃了.没想到现在学弟居然写出这种代码来,大吃一惊附加 ...
随机推荐
- 如何在CentOS 7上安装Munin
在CentOS 7上安装Munin 首先我们需要在我们的系统中添加EPEL仓库. yum install epel-release 步骤2.安装LAMP(Linux,Apache,MariaDB,PH ...
- 安装sass报错
ERROR in Cannot find module 'node-sass' 执行:npm install sass-loader node-sass webpack --save-dev即可
- vue系列之过渡效果
参考地址:http://cn.vuejs.org/v2/guide/transitions.html vue2.0,要想实现过渡效果,要用transition组件 代码: <div id=&qu ...
- SQL类型转换和数学函数
- eclipse安装主题插件(Color Theme)
点击“Help”--> Install New Software Name:ColorThemeLocation:http://eclipse-color-theme.github.io/upd ...
- 性能测试十一:jmeter进阶之java请求
使用Java编写JDBC脚本对Mysql进行增删改查等操作的性能测试 使用Jmeter提供的脚本框架依赖的jar包(分别在jmeter目录下的lib和ext目录下) ApacheJMeter_core ...
- Fiddler抓包5-接口测试(Composer)
前言 Fiddler最大的优势在于抓包,我们大部分使用的功能也在抓包的功能上,fiddler做接口测试也是非常方便的. 对应没有接口测试文档的时候,可以直接抓完包后,copy请求参数,修改下就可以了. ...
- python 全栈开发,Day15(递归函数,二分查找法)
一.递归函数 江湖上流传这这样一句话叫做:人理解循环,神理解递归.所以你可别小看了递归函数,很多人被拦在大神的门槛外这么多年,就是因为没能领悟递归的真谛. 递归函数:在一个函数里执行再调用这个函数本身 ...
- PDA智能程序访问WebService,报告“未能建立与网络的连接”
其实就是你没又连接上网络.首先下个第三方软件关于vs模拟器连接的.然后根据以下说明操作就可以连接了在确保主机已连上互联网的情况下,按以下步骤设置: 1.打开ActiveSync ,点击“文件”——&g ...
- python全栈开发day29-网络编程之socket常见方法,socketserver模块,ftp作业
一.昨日内容回顾 1.arp协议含义 2.子网,子网掩码 3.两台电脑在网络中怎么通信的? 4.tcp和udp socket编码 5.tcp和udp协议的区别 6.tcp三次握手和四次挥手,syn洪攻 ...