zoukankan      html  css  js  c++  java
  • HDU-4332-Constructing Chimney

    题目描述

    (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=)(egin{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
    ",++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;
    }
    
  • 相关阅读:
    李晋的YIM每日签名
    C语言的基础知识
    数据库的分页方法总结
    C#操作XML的代码
    ASP文件操作的类
    spring配置文件的基本语法
    预测球队比赛成绩
    文件的读写和我的第一个网页
    python中关于turtle库的学习笔记
    python科学计算与可视化
  • 原文地址:https://www.cnblogs.com/dsjkafdsaf/p/11323885.html
Copyright © 2011-2022 走看看