1. 程式人生 > >【2017廣西邀請賽】hdu 6185 Covering 矩陣快速冪

【2017廣西邀請賽】hdu 6185 Covering 矩陣快速冪

Problem Description Bob's school has a big playground, boys and girls always play games here after school.

To protect boys and girls from getting hurt when playing happily on the playground, rich boy Bob decided to cover the playground using his carpets.

Meanwhile, Bob is a mean boy, so he acquired that his carpets can not overlap one cell twice or more.

He has infinite carpets with sizes of 1×2 and 2×1
, and the size of the playground is 4×n.

Can you tell Bob the total number of schemes where the carpets can cover the playground completely without overlapping?

Input There are no more than 5000 test cases. 

Each test case only contains one positive integer n in a line.

1n1018

Output For each test cases, output the answer mod 1000000007 in a line.

Sample Input 1 2
Sample Output 1 5 題意:

用1*2規格的地毯去鋪4*n規格的地面,告訴你n,問有多少種不同的方案使得地面恰好被鋪滿且地毯不重疊。


思路:

骨牌覆蓋的方法構造的矩陣太大,會超時。

手動推出遞迴式 f[n]=f[n-1]+5f[n-2]+f[n-3]-f[n-4]。然後再用矩陣快速冪即可。

推導過程:http://blog.csdn.net/elbadaernu/article/details/77825979

//
//  main.cpp
//  1004
//
//  Created by zc on 2017/9/6.
//  Copyright © 2017年 zc. All rights reserved.
//
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
#define ll long long

using namespace std;

typedef vector<ll> vec;
typedef vector<vec> mat;
const ll MOD=1000000007;

mat mul(mat &A,mat &B)
{
    mat C(A.size(),vec(B[0].size()));
    for(int i=0;i<A.size();i++)
        for(int k=0;k<B.size();k++)
            for(int j=0;j<B[0].size();j++)
                C[i][j]=(C[i][j]+A[i][k]*B[k][j])%MOD;
    return C;
}

mat pow(mat A, ll n)
{
    mat B(A.size(),vec(A.size()));
    for(int i=0;i<A.size();i++) B[i][i]=1;
    while(n>0)
    {
        if(n&1) B=mul(B,A);
        A=mul(A,A);
        n>>=1;
    }
    return B;
}

int ans[5]={0,1,5,11,36};

int main()
{
    ll n;
    mat A(4,vec(4));
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
            A[i][j]=0;
    A[0][0]=A[0][1]=A[1][2]=A[2][0]=A[2][3]=1;
    A[1][0]=5;A[3][0]=-1;
    while(~scanf("%lld",&n))
    {
        if(n<5)
        {
            printf("%d\n",ans[n]);
            continue;
        }
        mat C=pow(A,n-4);
        mat B(1,vec(4));
        B[0][0]=36;B[0][1]=11;B[0][2]=5;B[0][3]=1;
        B=mul(B,C);
        printf("%lld\n",(B[0][0]+MOD)%MOD);
    }
}