[GXOI/GZOI2019]逼死強迫症

一、題目

點此看題

二、解法

f[i]f[i]爲大小爲2×i2\times i的矩陣填充的方案數,首先考慮不放特殊格子(1×11\times 1),那麼可以從f[i1]f[i-1]f[i2]f[i-2]轉移而來。考慮放特殊格子的情況,無論是放上面還是放下面,前面的格子的放法總是唯一的(和間隔的奇偶性有關),而且一定是要空兩格的,設g[i]g[i]爲大小爲2×i2\times i的矩陣只用2×12\times 1的小矩陣填充的方案數,那麼f[i]f[i]還可以從2j=1i3g[j]2\sum_{j=1}^{i-3} g[j]轉移過來,綜上我們可以寫出轉移方程:
f[i]=f[i1]+f[i2]+2(g[j1]1)f[i]=f[i-1]+f[i-2]+2(g[j-1]-1)這裏對轉移方程進行了簡寫,首先從dpdp的角度可得gg是一個斐波那契數列,要證明一個結論:i=1ng[i]=g[n+2]1\sum_{i=1}^n g[i]=g[n+2]-1,可以用歸納法,當n=1n=1時成立,假設n=kn=k時成立,那麼i=1kg[i]+g[k+1]=g[k+2]1+g[k+1]\sum_{i=1}^k g[i]+g[k+1]=g[k+2]-1+g[k+1],即i=1k+1g[i]=g[k+3]1\sum_{i=1}^{k+1}g[i]=g[k+3]-1,故n=k+1n=k+1時也成立,證畢。

顯然上面的dpdp可以用矩陣加速,如果不會構造矩陣的童鞋可以看下面的圖:
在這裏插入圖片描述
時間複雜度O(125×Tlogn)O(125\times T\log n),貼個代碼qwqqwq

#include <cstdio>
#include <cstring>
#define int long long
const int MOD = 1e9+7;
int read()
{
    int x=0,flag=1;char c;
    while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
    while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*flag;
}
int T,n;
struct Matrix
{
    int n,m,a[8][8];
    Matrix() {n=m=0;memset(a,0,sizeof a);}
    Matrix operator * (const Matrix &b) const
    {
        Matrix r;
        r.n=n;r.m=b.m;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                for(int k=1;k<=b.m;k++)
                {
                    r.a[i][k]=(r.a[i][k]+a[i][j]*b.a[j][k])%MOD;
                    r.a[i][k]=(r.a[i][k]+MOD)%MOD;
                }
        return r;
    }
}A,F;
Matrix qkpow(Matrix a,int b)
{
    Matrix r;
    r.n=r.m=a.n;
    for(int i=1;i<=r.n;i++)
        r.a[i][i]=1;
    while(b>0)
    {
        if(b&1) r=r*a;
        a=a*a;
        b>>=1;
    }
    return r;
}
signed main()
{
    T=read();
    while(T--)
    {
        n=read();
        if(n<=2)
        {
            puts("0");
            continue;
        }
        A.n=A.m=F.n=5;F.m=1;
        A.a[1][1]=A.a[1][2]=A.a[2][1]=
        A.a[3][3]=A.a[3][4]=A.a[4][3]=A.a[5][5]=1;
        A.a[1][3]=2;A.a[1][5]=-2;
        F.a[3][1]=2;F.a[4][1]=F.a[5][1]=1;
        printf("%lld\n",(qkpow(A,n-2)*F).a[1][1]);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章