hihoCoder #1143 : 骨牌覆蓋問題·一(矩陣乘法)

1143 : 骨牌覆蓋問題·一

時間限制:10000ms
單點時限:1000ms
內存限制:256MB
描述
骨牌,一種古老的玩具。今天我們要研究的是骨牌的覆蓋問題:
我們有一個2xN的長條形棋盤,然後用1x2的骨牌去覆蓋整個棋盤。對於這個棋盤,一共有多少種不同的覆蓋方法呢?
舉個例子,對於長度爲1到3的棋盤,我們有下面幾種覆蓋方式:
week41_1.PNG
提示:骨牌覆蓋
提示:如何快速計算結果
輸入
第1行:1個整數N。表示棋盤長度。1≤N≤100,000,000
輸出
第1行:1個整數,表示覆蓋方案數 MOD 19999997
樣例輸入
62247088
樣例輸出
17748018

/*
遞推式:f[i]=f[i-1]+f[i-2].
然後就是斐波那契了... 
*/
#include<iostream>
#include<cstdio>
#define mod 19999997
#define LL long long
using namespace std;
LL n,ans[3][3],b[3][3],c[3][3];
void mi()
{
    while(n)
    {
        if(n&1)
        {
            for(int i=1;i<=2;i++)
              for(int j=1;j<=2;j++)
                for(int k=1;k<=2;k++)
                  c[i][j]=(c[i][j]+ans[i][k]*b[k][j]%mod)%mod;
            for(int i=1;i<=2;i++)
              for(int j=1;j<=2;j++)
                ans[i][j]=c[i][j],c[i][j]=0;
        }
        for(int i=1;i<=2;i++)
          for(int j=1;j<=2;j++)
            for(int k=1;k<=2;k++)
              c[i][j]=(c[i][j]+b[i][k]*b[k][j]%mod)%mod;
        for(int i=1;i<=2;i++)
          for(int j=1;j<=2;j++)
            b[i][j]=c[i][j],c[i][j]=0;
        n>>=1;
    }
}
void slove()
{
    n--;
    ans[1][1]=2,ans[1][2]=1;
    b[1][1]=b[1][2]=b[2][1]=1;
    mi();
    cout<<ans[1][2];
}
int main()
{
    cin>>n;
    slove();
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章