xdoj-1111

对于一排n个正方形,有f(n)种方案达成目标,若第n个块是白色,则有f(n-1)种方案,若第n个块是黑色,则第n-1个块必为白色,那么有f(n-2)+n-2种方案。
则f(n)=f(n-1)+f(n-2)+n-2 。
写成矩阵形式:
(https://img-blog.csdn.net/20161011211956406)
例如:(i,j)表示i个空涂j个的种类数
(9,2)=(7,1)+(6,1)+(5,1)+(4,1)+(3,1)+(2,1)+(1,1)
(9,3)=(7,2)+(6,2)+(5,2)+(4,2)+(3,2)
(9,4)=(7,3)+(6,3)+(5,3)
(9,5)=(7,4)
(8,2)=(6,1)+(5,1)+(4,1)+(3,1)+(2,1)+(1,1)
(8,3)=(6,2)+(5,2)+(4,2)+(3,2)
(8,4)=(6,3)+(5,3)

#include<cstdio>
#include<cstring>
typedef long long ll;
const ll mod=1e9+7;
struct Mat
{
    ll mat[4][4];
};
Mat Mult(Mat a,Mat b)
{
    Mat c;
    memset(c.mat,0,sizeof(c.mat));
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
            for(int k=0;k<4;k++)
                c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod;
    return c;
}

Mat QMult(Mat a,ll b)
{
    Mat c;
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
            c.mat[i][j]=i==j;
    while(b){
        if(b&1)
            c=Mult(c,a);
        a=Mult(a,a);
        b>>=1;
    }
    return c;
}

int main()
{
    ll n;
    while(~scanf("%lld",&n))
    {
        Mat res;
        if(n==2)
        {
            puts("0");
            continue;
        }
        else if(n==3)
        {
            puts("1");
            continue;
        }
        memset(res.mat,0,sizeof(res.mat));
        res.mat[0][0]=res.mat[0][1]=res.mat[0][2]=res.mat[1][0]=1;
        res.mat[2][2]=res.mat[2][3]=res.mat[3][3]=1;
        res=QMult(res,n-3);
        printf("%lld\n",(res.mat[0][0]+2*res.mat[0][2]+res.mat[0][3])%mod);
    }
    return 0;
 } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值