• 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;
    }
  • 相关阅读:
    html实现虚线分隔线3例
    sql server 中将由逗号“,”分割的一个字符串,转换为一个表,并应用与 in 条件
    在Repeater中添加runat="server"的div,并控制
    Oracle中实现自增长列(转)
    SQL中按月进行分组(转)
    复制到剪切板js代码(转)
    如何使 Menu控件的链接打开指定的框架页(转)
    RadioButtonList限制每行"项"的个数
    Repeater_ItemDataBound 中用字段名获取值
    IIS7.0下配置Asp项目
  • 原文地址:https://www.cnblogs.com/z1141000271/p/7747781.html
Copyright © 2020-2023  润新知