zoukankan      html  css  js  c++  java
  • luogu P5303 [GXOI/GZOI2019]逼死强迫症

    传送门

    只有两行,考虑递推,设(f_i)为没有那两个(1*1)的,前(i)列的方案,可以发现一次可以放一个竖的或两个横的,也就是(f_i=f_{i-1}+f_{i-2})

    再设(g_i)表示有那两个(1*1)的,前(i)列的方案,首先和(f)类似,可以放一个竖的或两个横的(1*2),然后(1*1)可以放出长度为奇数,(ge3)的两种矩形,或者长度为偶数,(ge4)的两种矩形,所以$$g_i=g_{i-1}+g_{i-2}+(2sum_{j=3}^{i-jge 0} [jmod 2=1]f_{i-j})+(2sum_{j=4}^{i-jge 0} [jmod 2=0]f_{i-j})$$

    然后可以发现(sum_{j=3}^{i-jge 0} [jmod 2=1]f_{i-j}=f_{i-2}-1),(sum_{j=4}^{i-jge 0} [jmod 2=0]f_{i-j}=f_{i-3}),所以$$g_i=g_{i-1}+g_{i-2}+2(f_{i-2}-1)+2f_{i-3}$$

    注意(n)很大,要使用矩乘优化

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<map>
    #include<set>
    #define LL long long
    #define db double
    
    using namespace std;
    const int mod=1e9+7;
    int rd()
    {
        int x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        return x*w;
    }
    struct matrix
    {
        int a[6][6];
        matrix(){memset(a,0,sizeof(a));}
        void inii(){for(int i=0;i<6;++i) a[i][i]=1;}
        matrix operator * (const matrix &bb) const
        {
            matrix an;
            for(int i=0;i<6;++i)
                for(int j=0;j<6;++j)
                {
                    LL nw=0;
                    for(int k=0;k<6;++k) nw+=1ll*a[i][k]*bb.a[k][j];
                    an.a[i][j]=nw%mod;
                }
            return an;
        }
        matrix operator ^ (const LL &bb) const
       	{
            matrix an,a=*this;
            an.inii();
            LL b=bb;
            while(b)
            {
                if(b&1) an=an*a;
                a=a*a,b>>=1;
            }
            return an;
        }
    }aa,bb;
    
    int main()
    {
        aa.a[0][0]=aa.a[0][1]=1,aa.a[0][5]=mod-1;
        bb.a[0][0]=bb.a[1][0]=bb.a[0][1]=bb.a[1][2]=1;
        bb.a[3][3]=bb.a[4][3]=bb.a[3][4]=bb.a[5][5]=1;
        bb.a[1][3]=bb.a[2][3]=2,bb.a[5][3]=2;
        int T=rd();
        while(T--) printf("%d
    ",(aa*(bb^(rd()-1))).a[0][3]);
        return 0;
    }
    
  • 相关阅读:
    Dev XtraTreeList 学习
    DataGridView单元格显示GIF图片
    如何在.NET上处理二维码
    设计模式之UML类图的常见关系(一)
    .NET常用操作小知识
    Sql Server 存储过程使用技巧
    WinForm中如何判断关闭事件来源于用户点击右上角的“关闭”按钮
    WinFrom 安装包制作
    DBHelper数据库操作类(二)
    spring cloud zipkin
  • 原文地址:https://www.cnblogs.com/smyjr/p/10763306.html
Copyright © 2011-2022 走看看