zoukankan      html  css  js  c++  java
  • 【hdu6185】Covering(骨牌覆盖)

    2017ACM/ICPC广西邀请赛-重现赛1004Covering

    题意

    n*4的格子,用1*2和2*1的砖块覆盖。问方案数(mod 1e9+7)。(n不超过1e9)

    题解

    递推了个式子然后错位相减。
    f[n] =f[n-1]+4f[n-2]+2f[n-3]+3f[n-4]+2f[n-5]+2f[n-6]+..+(x%2?2:3)f[n-x]
    f[n-2]= f[n-3]+4f[n-4]+2f[n-5]+3f[n-6]+..+(x%2?2:3)f[n-x]
    f[n] =f[n-1]+5f[n-2]+ f[n-3]-f[n-4]
    再用矩阵快速幂。
    另外,这题可以先用暴力的dfs或者状态压缩dp求得前几项,然后套BM板子得出递推式。
    不过,官方题解的方法是状态压缩加矩阵快速幂优化:
    只考虑一列的状态,0表示没有被覆盖,1表示被覆盖了,只可能有0000,1111,1001,0110,1100,0011。
    dp[i][j]表示前i-1列覆盖满,第i列状态为j的方案数。考虑转移,然后a[i][j]==1就是状态i可以由状态j转移过来,那么就可以矩阵快速幂加速了。

    --
    51nod 上的骨牌覆盖 V2,类似。a数组可以dfs出来。

    代码

    typedef long long ll;
    typedef vector<ll> VI;
    typedef vector<VI> Mat;
    const ll mod=1000000007;
    Mat mul(Mat &a,Mat &b){
    	Mat c(SZ(a), VI(SZ(b[0])));
    	rep(i,0,SZ(a))rep(j,0,SZ(b[0]))rep(k,0,SZ(b))
    		c[i][j]=(c[i][j]+a[i][k]*b[k][j])%mod;
    	return c;
    }
    Mat qpow(Mat a,ll b){
    	Mat c(SZ(a), VI(SZ(a)));
    	rep(i,0,SZ(a))c[i][i]=1;
    	for(;b;b>>=1,a=mul(a,a))if(b&1)c=mul(c,a);
    	return c;
    }
    
    int main(){
    	Mat a(4,VI(4));
    	a[0]=VI{1,5,1,-1};
    	rep(i,0,3)a[i+1][i]=1;
    	ll n;
    	while(~scanf("%lld",&n)){
    		if(n==1)puts("1");
    		else if(n==2)puts("5");
    		else if(n==3)puts("11");
    		else if(n==4)puts("36");
    		else{
    			Mat c=qpow(a,n-4);
    			printf("%lld
    ",((c[0][0]*36+c[0][1]*11+c[0][2]*5+c[0][3])%mod+mod)%mod);
    		}
    	}
    	return 0;
    }
    

    状态压缩

    int main() {
    	Mat a(6,VI(6));
    	a[0]=VI{1,1,1,1,1,0};
    	a[1]=VI{1,0,0,0,0,0};
    	a[2]=VI{1,0,0,1,0,0};
    	a[3]=VI{1,0,1,0,0,0};
    	a[4]=VI{1,0,0,0,0,1};
    	a[5]=VI{0,0,0,0,1,0};
    	ll n;
    	while(~scanf("%lld",&n)){
    		printf("%lld
    ",qpow(a,n)[0][0]);
    	}
    	return 0;
    }
    

    骨牌覆盖 V2

    const int N=1<<5;
    int n,m;
    Mat a(N,VI(N));
    void dfs(int c,int pre,int cur){
    	if(c>n)return;
    	if(c==n){
    		++a[pre][cur];
    		return;
    	}
    	dfs(c+1,pre<<1,cur<<1|1);//竖着放
    	dfs(c+1,pre<<1|1,cur<<1);//不能放
    	dfs(c+2,pre<<2,cur<<2);//横着放
    }
    int main() {
    	while(~scanf("%d%d",&m,&n)){
    		rep(i,0,SZ(a))rep(j,0,SZ(a[i]))a[i][j]=0;
    		dfs(0,0,0);
    		printf("%lld
    ",qpow(a,m)[0][0]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    宿主机无法访问CentOS7上Jenkins服务的解决办法
    415. Add Strings
    367. Valid Perfect Square
    326. Power of Three
    258. Add Digits
    231. Power of Two
    204. Count Primes
    202. Happy Number
    172. Factorial Trailing Zeroes
    171. Excel Sheet Column Number
  • 原文地址:https://www.cnblogs.com/flipped/p/7467931.html
Copyright © 2011-2022 走看看