题目描述

用\(1*1*2\)的砖头摆出如图所示的烟囱,可以横着摆也可以竖着摆,求摆出\(n\)层高的烟囱会有多少种不同的方案。

Input

一共有\(T\)组数据。

每组数据包含一个\(n(1 \le n \le 1e9)\)。

Output

对于每组数据,输出方案数模\(1000000007\)。

Sample Input

2
1
2

Sample Output

Case 1: 2
Case 2: 49

看到这个数据范围就是矩阵优化递推了。。

很显然,对于一层的某个状态其中的某个格子放或者是不放可以利用状态压缩来\(DP\)。

\(DP\)转移方程为\(dp[i][j]+=dp[i-1][k],j可以转移到k\)。

其中,\(dp[i][j]\)表示第\(i\)层,状态为\(j\)的方案数。

那么,暴力转移的复杂度为\(O(n*256^2)\)。

由于每层的转移是唯一的,所以利用矩阵优化。

对于一个状态\(i\)我们暴力枚举其他状态\(j\),\(check\)能不能相进行转移。

若能转移\(g_i,_j\)为\(1\),否则为\(0\)。

构造出转移矩阵\(g=\)\(\begin{pmatrix}
0 & 0 & 1 & \cdots & 1 \\
1 & 0 & 0 & \cdots & 0 \\ 0 & 1 & 0 & \cdots & 0 \\\vdots & \vdots & \vdots & \ddots & \vdots \\
0 & 0 & 0 & \cdots & 0 \\
\end{pmatrix}\),利用矩阵快速幂求解。

时间复杂度降为\(O(log_n*256^3)\)。

有点小大,还有多组数据,不是很稳!!!

那么考虑剪枝。

我们把那张\(256*256\)的表打出来,发现矩阵的大部分是\(0\),也就是说,有大部分的状态是无用的,也就是说一些状态是永远也更新不到的,我们可以把这些状态去掉。

我们发现那些只有每层奇数个格子有的状态是无用的,可以直接少掉一半的复杂度,时间复杂度\(O(log_n*128^3)\)。

卡一卡常还是能过的。

其实还可以在进行优化,机房大佬\(gxy\)直接把代码优化到\(0ms\)。

据说是先缩到\(128*128\),再四个方向旋转去重,再对称和镜像去重减到只有十几种情况,打一个表解决。。。

orzorz...

代码如下

#include <bits/stdc++.h>

using namespace std;

#define LL long long
#define u64 unsigned long long
#define u32 unsigned int
#define reg register
#define Raed Read
#define debug(x) cerr<<#x<<" = "<<x<<endl;
#define rep(a,b,c) for(reg int a=(b),a##_end_=(c); a<=a##_end_; ++a)
#define ret(a,b,c) for(reg int a=(b),a##_end_=(c); a<a##_end_; ++a)
#define drep(a,b,c) for(reg int a=(b),a##_end_=(c); a>=a##_end_; --a)
#define erep(i,x) for(reg int i=Head[x]; i; i=Nxt[i]) inline int Read() {
int res = 0, f = 1;
char c;
while (c = getchar(), c < 48 || c > 57)if (c == '-')f = 0;
do res = (res << 3) + (res << 1) + (c ^ 48);
while (c = getchar(), c >= 48 && c <= 57);
return f ? res : -res;
} template<class T>inline bool Min(T &a, T const&b) {
return a > b ? a = b, 1 : 0;
}
template<class T>inline bool Max(T &a, T const&b) {
return a < b ? a = b, 1 : 0;
} const int N=305,M=1e5+5,mod=1e9+7; bool MOP1; int n,m,cnt,Id[N]; struct Matrix {
int Num[N][N];
inline void clear(void) {
memset(Num,0,sizeof Num);
}
inline void Init(void) {
rep(i,1,cnt)Num[i][i]=1;
}
inline Matrix operator*(Matrix _)const {
Matrix Ans;
Ans.clear();
rep(i,1,cnt)rep(j,1,cnt)rep(k,1,cnt)Ans.Num[i][j]=(Ans.Num[i][j]+1ll*Num[i][k]*_.Num[k][j])%mod;
return Ans;
}
} us; inline Matrix qpow(Matrix A,int k) {
Matrix res;
res.clear(),res.Init();
while(k) {
if(k&1)res=res*A;
A=A*A,k>>=1;
}
return res;
} int Sum(int x) {
int tot=0;
while(x)x^=x&-x,tot++;
return tot;
} bool check(int x,int y) {
int TT=x|y;
if(TT!=255)return false;
TT=x&y;
if(TT==255)return true;
while(TT&1)TT=1<<7|(TT>>1);
int tot=0;
rep(i,0,8) {
if(i<8&&(TT>>i)&1)tot++;
else if(tot&1)return false;
}
return true;
} bool MOP2; inline void _main(void) {
// cerr<<"M="<<(&MOP2-&MOP1)/1024.0/1024.0<<endl;
int T=Raed(),m=1<<8;
us.clear();
ret(i,0,m) {
if(Sum(i)&1)continue;
Id[i]=++cnt;
}
ret(i,0,m)if(Id[i])ret(j,0,m)if(Id[j]&&check(i,j))us.Num[Id[i]][Id[j]]=1;
us.Num[Id[255]][Id[255]]++;
int Case=0;
while(T--) {
int n=Read();
Matrix Ans=qpow(us,n);
printf("Case %d: %d\n",++Case,Ans.Num[Id[255]][Id[255]]);
}
} signed main() {
#define offline1
#ifdef offline
freopen("chessboard.in", "r", stdin);
freopen("chessboard.out", "w", stdout);
_main();
fclose(stdin);
fclose(stdout);
#else
_main();
#endif
return 0;
}

HDU-4332-Constructing Chimney的更多相关文章

  1. HDU 1102 Constructing Roads, Prim+优先队列

    题目链接:HDU 1102 Constructing Roads Constructing Roads Problem Description There are N villages, which ...

  2. HDOJ(HDU).1025 Constructing Roads In JGShining's Kingdom (DP)

    HDOJ(HDU).1025 Constructing Roads In JGShining's Kingdom (DP) 点我挑战题目 题目分析 题目大意就是给出两两配对的poor city和ric ...

  3. HDU 1025 Constructing Roads In JGShining's Kingdom(二维LIS)

    Constructing Roads In JGShining's Kingdom Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65 ...

  4. hdu 1102 Constructing Roads Kruscal

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1102 题意:这道题实际上和hdu 1242 Rescue 非常相似,改变了输入方式之后, 本题实际上更 ...

  5. HDU 1102(Constructing Roads)(最小生成树之prim算法)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1102 Constructing Roads Time Limit: 2000/1000 MS (Ja ...

  6. hdu 1102 Constructing Roads (Prim算法)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1102 Constructing Roads Time Limit: 2000/1000 MS (Jav ...

  7. hdu 1102 Constructing Roads (最小生成树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1102 Constructing Roads Time Limit: 2000/1000 MS (Jav ...

  8. [ACM] hdu 1025 Constructing Roads In JGShining's Kingdom (最长递增子序列,lower_bound使用)

    Constructing Roads In JGShining's Kingdom Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65 ...

  9. HDU 1102 Constructing Roads

    Constructing Roads Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  10. HDU 1025 Constructing Roads In JGShining's Kingdom(求最长上升子序列nlogn算法)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1025 解题报告:先把输入按照r从小到大的顺序排个序,然后就转化成了求p的最长上升子序列问题了,当然按p ...

随机推荐

  1. jquery die()方法 语法

    jquery die()方法 语法 作用:die() 方法移除所有通过 live() 方法向指定元素添加的一个或多个事件处理程序.直线电机参数 语法:$(selector).die(event,fun ...

  2. 总结JavaScript中浏览器的兼容问题

    浅析JavaScript中浏览器的兼容问题 浏览器兼容性问题是在实际开发中容易忽略而又最重要的一部分.我们在讲老版本浏览器兼容问题之前,首先要了解什么是能力检测,它是来检测浏览器有没有这种能力,即判断 ...

  3. 分块查找(Blocking Search)

    1.定义 分块查找(Blocking Search)又称索引顺序查找.它是一种性能介于顺序查找和二分查找之间的查找方法. 2.基本思想 分块查找的基本思想是: (1)首先查找索引表 索引表是有序表,可 ...

  4. 【封装工程】OI/ACM常用封装

    前言 笔者有的时候无聊,就将一些奇怪的东西封装起来. 范围主要是在\(OI\)或者\(ACM\)中的常见数据结构等. 随着笔者的能力的提升,可能会对原来的封装程序进行修改,并且保留原来的版本. [ST ...

  5. OCWA提高组模拟赛一 Solution

    Problem A RecMin 给出一个$n \times m$的矩阵,其中$1 \leq n,m \leq 3\ times 10^3$ 给出整数$a,b$,求出在矩阵中所有$a\ times b ...

  6. Sonar页面Author页面展示

    文主要记录通过Jenkins集成git .svn .sonarqube,获取源码后自动构建进行sonar scanner代码审查,并分析在sonar能够展示Author的原因. 一.Sonar通过je ...

  7. [LOJ3119][CTS2019|CTSC2019]随机立方体:组合数学+二项式反演

    分析 感觉这道题的计数方法好厉害.. 一个直观的思路是,把题目转化为求至少有\(k\)个极大的数的概率. 考虑这样一个事实,如果钦定\((1,1,1),(2,2,2),...,(k,k,k)\)是那\ ...

  8. [CSP-S模拟测试]:装饰(状压DP)

    题目传送门(内部题114) 输入格式 第一行一个正整数$n$. 接下来一行$n-1$个正整数,第$i$个数为$f_{i+1}$. 接下来一行$n$个数,若第$i$个数为$0$则表示林先森希望$i$号点 ...

  9. 数据库 mysql 操作

    安装好xammp,打开阿帕奇和数据库服务: 点击右侧 shell 按钮,进入命令行: 首先,利用超级管理员权限进入数据库: mysql -uroot -p enter,再enter 把下述代码复制进命 ...

  10. 【Spark机器学习速成宝典】模型篇07梯度提升树【Gradient-Boosted Trees】(Python版)

    目录 梯度提升树原理 梯度提升树代码(Spark Python) 梯度提升树原理 待续... 返回目录 梯度提升树代码(Spark Python) 代码里数据:https://pan.baidu.co ...