hdu 6185 递推+矩阵快速幂

思路:考虑全部铺满时,前2列的放法。有如下5种情况:(转自http://blog.csdn.net/elbadaernu/article/details/77825979 写的很详细 膜一下) 
这里写图片描述 
假设f(n)表示列数为n时的方案数,那么这五种情况合法的方案数相加即f(n)。这里n大于2. 
第一种的方案数即f(n-1),第二种的方案数即f(n-2)。 
第三种:接下来有两种方案可以选择,一是用一块毛毯去填补第二列的空缺部分,那么此时接下来填补的方案数为f(n-2),二是用两块毛毯去填补,这样的话第三列又会形成一个新的空缺,如下图所示: 
这里写图片描述 
所以我们又可以像之前那样去填补,所以第三种的方案数为f(n-2)+f(n-3)+f(n-4)+……+f(0),f(0)=1 
第四种:情况与第三种类似,方案数与其相同。 
第五种:开始的选择也是两种,一是选择一块毯子去填,这样接下来填补的方案数为f(n-2),或者选择两块去填,然后,为了使它铺满,我们还得用两块毛毯去铺上下两个空缺的地方,这时的空缺形成了之前的情况,如下图所示: 
这里写图片描述 
以此类推,所以第五种的方案数为f(n-2)+f(n-4)+f(n-6)+……+f(1)或者f(0)(偶数0,奇数1)

所以总的方案数 
f(n)=f(n-1)+f(n-2)+2*(f(n-2)+f(n-3)+……+f(0))+f(n-2)+f(n-4)+f(n-6)+……+f(1)或者f(0) 
然后将n=n-2代入上式,然后用f(n)减去f(n-2), 
化简得f(n)=f(n-1)+5*f(n-2)+f(n-3)-f(n-4)。 

然后自己的矩阵快速幂也换了一个较为通用的写法:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
struct Martix
{
    ll mp[5][5];
    ll r,c;
};
Martix mul(Martix a,Martix b)
{
    Martix c;
    c.r=a.r;
    c.c=b.c;
    for(int i=0;i<a.r;i++)
    {
        for(int j=0;j<b.c;j++)
        {
            c.mp[i][j]=0;
            for(int k=0;k<a.c;k++)
            {
                c.mp[i][j]=(a.mp[i][k]*b.mp[k][j]+c.mp[i][j]+mod)%mod;
                c.mp[i][j]%=mod;
            }
        }
    }
    return c;
}
Martix ans;
Martix a;// 系数矩阵
void init()
{
    memset(ans.mp,0,sizeof(ans.mp));
    ans.r=2;
    ans.c=1;
    ans.mp[0][0]=36;
    ans.mp[1][0]=11;
    ans.mp[2][0]=5;
    ans.mp[3][0]=1;

    a.r=a.c=4;
    memset(a.mp,0,sizeof(a.mp));
    a.mp[0][0]=1;
    a.mp[0][1]=5;
    a.mp[0][2]=1;
    a.mp[0][3]=-1;
    a.mp[1][0]=a.mp[2][1]=a.mp[3][2]=1;
}
Martix pow(Martix x,ll k)
{
    Martix temp;
    temp.r=temp.c=x.r;
    memset(temp.mp,0,sizeof(temp.mp));
    for(int i=0;i<x.r;i++) // 单位矩阵
    {
        for(int j=0;j<x.c;j++) if(i==j) temp.mp[i][j]=1;
    }
    while(k)
    {
        if(k&1) temp=mul(x,temp);
        k/=2;
        x=mul(x,x);
    }
    return temp;
}
int main()
{
    ll n;

    while(cin>>n)
    {
        init();
        if(n==0)
        {
            cout<<1<<endl;
            continue;
        }
        if(n==1)
        {
            cout<<1<<endl;
            continue;
        }
        if(n==2)
        {
            cout<<5<<endl;
            continue;
        }
        if(n==3)
        {
            cout<<11<<endl;
            continue;
        }
        if(n==4)
        {
            cout<<36<<endl;
            continue;
        }
        a=pow(a,n-4);//
        ans=mul(a,ans);
        cout<<ans.mp[0][0]%mod<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/z1141000271/p/7747781.html