zoukankan      html  css  js  c++  java
  • HDU 4332 Contest 4

    顶好的一道题。其实,是POJ 2411的升级版。但POJ 2411我用的插头DP来做,一时没想到那道题怎么用状态DP,于是回头看POJ 2411那一道的状态DP,其实也很简单,就是每一行都设一个状态,用位来表示,如果上一行为0,则当前行必定是要竖着放的。填1.否则,当前行的位置可以横放填两个格子为1,也可以不放,为0.于是,看上一行的状态能转移到哪些状态,就可以了。

    这一道也是一样的想做法,DFS看开始时有哪些状态,记在一个一维矩阵里。因为有一些状态最开始是达不到的,如奇数个1,或者一些不连续1的状态。然后求转移矩阵(这个地方想了很久才想到,因为要做很多重复的工作,所以想到用矩阵)。求矩阵时,也用DFS就可以了。

    此处在矩阵相乘时有一个小优化,因为转移矩阵中含0较多,所以把中间变量K提到第一个循环。当含有0时就终止。因为这个地方由TLE,优化到了8000MS,也是满足了。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define LL __int64
    #define mod 1000000007
    using namespace std;
    
    struct Matrix{
    	LL ans[130][130];
    };
    Matrix pp[31];
    
    LL bgn[130];
    LL res[130];
    int only;
    int number[260];
    Matrix transfer;
    Matrix per;
    bool ok(int s){
    	int c=0;
    	for(int i=0;i<8;i++)
    	if(s&(1<<i)) c++;
    	if(c%2==0) return true;
    	return false;
    }
    
    Matrix operator *(Matrix a,Matrix b){
    	Matrix c;
    	for(int i=0;i<only;i++)
    	for(int j=0;j<only;j++)
    	c.ans[i][j]=0;
    	for(int k=0;k<only;k++)    //把k提到这里来就过了。。。哈哈,这也是一种优化啊,因为矩阵中0较多,避免了不必要的计算。 
    	for(int i=0;i<only;i++){
    		if(a.ans[i][k]==0) continue;
    		for(int j=0;j<only;j++){
    			c.ans[i][j]=(c.ans[i][j]+(a.ans[i][k]*b.ans[k][j])%mod)%mod;
    		}
    	}
    	return c;
    }
    
    void find_bgn(int state,int pos){
    	if(pos>=8) {
    		bgn[number[state]]++;
    		return ;
    	}
    	int tmp=state;
    	int i=pos;
    	if((state&(1<<i))==0&&(state&(1<<((i+1)%8)))==0){
    		tmp=state|(1<<i)|(1<<((i+1)%8));
    		find_bgn(tmp,i+2);
    	}
    	find_bgn(state,i+1);
    }
    
    void dfs(int pre,int state,int pos){
    	if(pos>=8) {
    		transfer.ans[number[pre]][number[state]]++;
    		return ;
    	}
    	int tmp=state;
    	int i=pos;
    	if((state&(1<<i))==0&&(state&(1<<((i+1)%8)))==0){
    		tmp=state|(1<<i)|(1<<((i+1)%8));
    		dfs(pre,tmp,i+2);
    	}
    	dfs(pre,state,i+1);
    }
    
    /*
    LL can(int a,int b)
    {
        int st,i,j;
        bool end=false;
        if(a==0)return b==255? 1LL:0;
        for(i=0;i<8;i++)
        {
            j=(i+7)%8;
            if((a&(1<<i))&&(a&(1<<j))==0)
            {
                st=i;
                break;
            }
        }
        for(i=st;i!=st||end==false;i=(i+1)%8)
        {
            end=true;
            j=(i+1)%8;
            if(0==(a&(1<<i)))
            {
                if(0==(b&(1<<i)))return 0;
            }
            else
            {
                if((a&(1<<j))&&(b&(1<<i))&&(b&(1<<j)))i++;
                else if((b&(1<<i))==0)continue;
                else return 0;
            }
        }
        return 1LL;
    }
    */
    void initial(){
    	only=0;
    	memset(number,-1,sizeof(number));
    	memset(transfer.ans,0,sizeof(transfer.ans));
    	for(int i=0;i<(1<<8);i++)
    	if(ok(i)) number[i]=only++;
    	
    	for(int i=0;i<only;i++)
    	for(int j=0;j<only;j++)
    	if(i==j) per.ans[i][i]=1;
    	else per.ans[i][j]=0;
    	
    	memset(bgn,0,sizeof(bgn));
    	find_bgn(0,0);
    	
    	for(int i=0;i<(1<<8);i++){
    		if(number[i]!=-1){
    			dfs(i,255-i,0);
    		}
    	}
    /*
      for(int i=0;i<1<<8;i++)
           for(int j=i+1;j<1<<8;j++)
           if(number[i]!=-1&&number[j]!=-1)
               transfer.ans[number[j]][number[i]]=transfer.ans[number[i]][number[j]]=can(i,j);
           transfer.ans[only-1][only-1]=2;	
       */    
    	for(int i=1;i<31;i++){
    		if(i==1)
    		pp[i]=transfer;
    		else
    		pp[i]=pp[i-1]*pp[i-1];
    	}
    }
    
    LL pow(int k){
    	Matrix ans=per,ats=transfer;
    	int c=1;
    	while(k){
    		if(k&1) ans=ans*pp[c];
    		k>>=1;
    		c++;
    	}
    	LL tmp=0;
    	for(int j=0;j<only;j++)
    	tmp=(tmp+(bgn[j]*ans.ans[j][only-1])%mod)%mod;
    	return tmp;
    }
    
    int main(){
    	initial();
    	int n,T,kase=0;
    	scanf("%d",&T);
    	while(T--){
    		scanf("%d",&n);
    		LL resul=pow(n-1);
    		printf("Case %d: %I64d
    ",++kase,resul);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    用几何画板画三星状图形的方法有哪些
    ChemDraw 15.1 Pro插入阿尔法可以这样做
    用MathType编辑异或与非符号有什么方法
    整合Thinkphp数据库基本操作CURD,界面datagrid采用EasyUi的Demo
    可编辑表格
    jQuery一步一步实现跨浏览器的可编辑表格,支持IE、Firefox、Safari、
    jfinal 使用类里的方法
    左右值无限分类实现算法
    PHP递归实现无限级分类
    ThinkPHP自动填充实现无限级分类的方法
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/4114924.html
Copyright © 2011-2022 走看看