zoukankan      html  css  js  c++  java
  • 1033 骨牌覆盖 V2(基于 状压DP的矩阵快速幂)

    基准时间限制:1 秒 空间限制:131072 KB 分值: 320 难度:7级算法题
     收藏
     关注
    在m*n的一个长方形方格中,用一个1*2的骨牌排满方格。问有多少种不同的排列方法。(n <= 5)
     
    例如:3 * 2的方格,共有3种不同的排法。(由于方案的数量巨大,只输出 Mod 10^9 + 7 的结果)
     
    Input
    2个数M N,中间用空格分隔(2 <= m <= 10^9,2 <= n <= 5)
    Output
    输出数量 Mod 10^9 + 7
    Input示例
    2 3
    Output示例
    3

    思路:m特别大 n特别小 思考用状压DP但是一看数据1e9解决不了怎么办呢?

    我们可以找到初始状态与下一个状态的矩阵的关系,代码实现如下

    void dfs(int i,int j,int k,int u)
    {
    	if(u == n){
    		x.s[i][k]++;
    		return;
    	}
    	if((j&(1<<u))){
    		dfs(i,j,k,u+1);
    		return;
    	}
    	dfs(i,j|(1<<u),k|(1<<u),u+1);
    	if(u+1<n && !(j&(1<<u)) && !(j&(1<<(u+1))))
    	{
    		dfs(i,j|(1<<u)|(1<<(u+1)),k,u+2);
    	}
    }
    for(int i = 0;i<num;i++){
    	dfs(i,i,0,0);
    }

    然后用矩阵快速幂优化就行了

    AC:代码  时间15ms

    #include <bits/stdc++.h>
    
    using namespace std; 
    
    typedef long long ll;
    typedef long long int lli;
    typedef unsigned long long llu;
    
    #define mod 1000000007
    
    const int maxn = 1<<5;
    int num,n,m;
    struct matrix{
    	ll s[maxn][maxn];
    }x;
    
    matrix MulMatrix(matrix a,matrix b,int c,int d,int e)
    {
    	matrix res;
    	for(int i = 0;i<c;i++){
    		for(int j = 0;j<d;j++){
    			int x = 0;
    			for(int k = 0;k<e;k++){
    				x = (x+(a.s[i][k]*b.s[k][j]))%mod;
    			}
    			res.s[i][j] = x;
    		}
    	}
    	return res;
    }
    
    matrix MatrixPow(matrix a,int b)
    {
    	matrix res;
    	memset(res.s,0,sizeof(res.s));
    	for(int i = 0;i<maxn;i++){
    		res.s[i][i] = 1;
    	}
    	while(b)
    	{
    		if(b&1){
    			res = MulMatrix(res,a,1,num,num);
    		}
    		b>>=1;
    		a = MulMatrix(a,a,num,num,num); 
    	}
    	return res;
    }
    
    void dfs(int i,int j,int k,int u)
    {
    	if(u == n){
    		x.s[i][k]++;
    		return;
    	}
    	if((j&(1<<u))){
    		dfs(i,j,k,u+1);
    		return;
    	}
    	dfs(i,j|(1<<u),k|(1<<u),u+1);
    	if(u+1<n && !(j&(1<<u)) && !(j&(1<<(u+1))))
    	{
    		dfs(i,j|(1<<u)|(1<<(u+1)),k,u+2);
    	}
    }
    
    int main()
    {
    
    	scanf("%d %d",&m,&n);
    	num = (1<<n);
    	memset(x.s,0,sizeof(x.s));
    	for(int i = 0;i<num;i++){
    		dfs(i,i,0,0);
    	}
    	matrix y = MatrixPow(x,m);
    	printf("%lld
    ",y.s[0][0]);
    	return 0;
    }


  • 相关阅读:
    Effective Java 的笔记(二)
    设计模式系列 装饰模式
    一道多线程题目的解决方案
    Effective Java 的笔记(一)
    Java 并发编程实践
    【转】微博技术底层架构的实现
    Head First JavaScript 笔记
    JVM 学习笔记 类的加载和执行
    背包问题
    Oracle 序列号通过定时任务重置
  • 原文地址:https://www.cnblogs.com/Nlifea/p/11745998.html
Copyright © 2011-2022 走看看