题目链接:

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的更多相关文章

  1. luogu1357 花园 状态压缩 矩阵快速幂

    题目大意 小L有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为1~N(2<=N<=10^15).他的环形花园每天都会换一个新花样,但他的花园都不外乎一个规则,任意相邻M(2<= ...

  2. 【状态压缩DP】HDU 4352 XHXJ'S LIS

    题目大意 Vjudge链接 定义一个数的内部LIS长度表示这个数每个数位构成的序列的LIS长度,给出区间\([l,r]\),求区间内内部LIS长度为\(k\)的数的个数. 输入格式 第一行给出数据组数 ...

  3. 矩阵乘法 --- hdu 4920 : Matrix multiplication

    Matrix multiplication Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/ ...

  4. 洛谷P1357 花园(状态压缩 + 矩阵快速幂加速递推)

    题目链接:传送门 题目: 题目描述 小L有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为1~N(<=N<=^).他的环形花园每天都会换一个新花样,但他的花园都不外乎一个规则,任意相邻 ...

  5. HDU - 6185 :Covering(矩阵乘法&状态压缩)

    Bob's school has a big playground, boys and girls always play games here after school. To protect bo ...

  6. HDU 5768 Lucky7 (容斥原理 + 中国剩余定理 + 状态压缩 + 带膜乘法)

    题意:……应该不用我说了,看起来就很容斥原理,很中国剩余定理…… 方法:因为题目中的n最大是15,使用状态压缩可以将所有的组合都举出来,然后再拆开成数组,进行中国剩余定理的运算,中国剩余定理能够求出同 ...

  7. HDU 4921 Map DFS+状态压缩+乘法计数

    算最多十条链,能截取某前缀段,每种方案都可以算出一个权值,每种方案的概率都是总数分之一,问最后能构成的所有可能方案数. 对计数原理不太敏感,知道是DFS先把链求出来,但是想怎么统计方案的时候想了好久, ...

  8. HDU 5607 graph(DP+矩阵乘法)

    [题目链接] http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=663&pid=1002 [题意] 给定一个有向 ...

  9. HDU 3681 Prison Break(状态压缩dp + BFS)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3681 前些天花时间看到的题目,但写出不来,弱弱的放弃了.没想到现在学弟居然写出这种代码来,大吃一惊附加 ...

随机推荐

  1. HTTP基础知识1

    HTTP 简介 HTTP协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准,它是基于TCP/IP ...

  2. typeof引发的思考

    今天在群里看到一位网友提问:var status=1; typeof status 结果输出什么 我会心一笑  ,这尼玛这么简单,一看就是‘number’,结果网友说不是number,而是string ...

  3. ios 侧边手势滑动返回 禁用/开启 功能

    // 禁用  返回手势       if ([self.navigationController respondsToSelector:@selector(interactivePopGestureR ...

  4. zoj3469 区间dp好题

    /* 按坐标排序 以餐厅为起点向两边扩展区间 dp[i][j][0]表示送完区间[i,j]的饭后停留在左边的代价 dp[i][j][1]表示送完区间[i,j]的饭后停留在右边的代价 */ #inclu ...

  5. zabbix server+agent+proxy搭建性能监控平台

    这是新找到了配置文件配置方法但未尝试 每个模块工作职责: Zabbix Server:负责接收agent发送的报告信息的核心组件,所有配置,统计数据及操作数据均由其组织进行: Database Sto ...

  6. python 全栈开发,Day65(MySQL练习题,参考答案)

    一.MySQL练习题 一.表关系 请创建如下表,并创建相关约束 二.操作表 1.自行创建测试数据 2.查询“生物”课程比“物理”课程成绩高的所有学生的学号.ps:针对的是自己的生物成绩比物理成绩高,再 ...

  7. Excel学习笔记:if({1,0})用法

    一.if函数 判断是否满足条件,满足则返回第2个参数,不满足则返回第3个参数. 使用格式:=if(A1>0,"正","负") 二.if({1,0})用法 ...

  8. AndroidStudio将html5打包成apk

    我想将html5的动画效果打包成手机app,以方便传播.而在android开发的组件中就直接由webview可以访问网页,另外在android工程中,assets文件夹下的内容是不会在被编译的,因此可 ...

  9. Python全局解释器锁

    超过十年以上,没有比解释器全局锁(GIL)让Python新手和专家更有挫折感或者更有好奇心.    Python的底层 要理解GIL的含义,我们需要从Python的基础讲起.像C++这样的语言是编译型 ...

  10. python:a += b 和 a = a + b

    在python中,不同的情况下,这两个表达式有着很大的区别: 如果a,b都是可变对象,例如list,a+=b实际是对a指向的地址上的值进行修改,即运算前后id(a)的值是不变的. 而a=a+b是不同的 ...