hihocoder #1162 矩陣加速dp

#1162 : 骨牌覆蓋問題·三

時間限制:10000ms
單點時限:1000ms
內存限制:256MB

描述

前兩週裏,咱們講解了2xN,3xN骨牌覆蓋的問題,而且引入了兩種不一樣的遞推方法。
這一次咱們再增強一次題目,對於給定的K和N,咱們須要去求KxN棋盤的覆蓋方案數。ios

提示:KxN骨牌覆蓋json

輸入

第1行:2個整數N。表示棋盤寬度爲k,長度爲N。2≤K≤7,1≤N≤100,000,000vim

輸出

第1行:1個整數,表示覆蓋方案數 MOD 12357api

樣例輸入
2 62247088
樣例輸出
1399
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MOD=12357;
int m,n;
struct Lu { int mx[140][140]; }L1,L2;
void dfs(int now,int next,int col)
{
    if(col==m){
        L1.mx[now][next]=1;//表示now狀態可以轉移到next狀態
        return;
    }
    dfs((now<<1)+1,next<<1,col+1);//不放
    dfs(now<<1,(next<<1)+1,col+1);//豎放
    if(col+2<=m) dfs((now<<2)+3,(next<<2)+3,col+2);//橫放
}
Lu multi(Lu a,Lu b)
{
    Lu c;
    for(int i=0;i<(1<<m);i++){
        for(int j=0;j<(1<<m);j++){
            c.mx[i][j]=0;
            for(int k=0;k<(1<<m);k++)
                c.mx[i][j]=(c.mx[i][j]+a.mx[i][k]*b.mx[k][j])%MOD;
        }
    }
    return c;
}
int solve(int x)
{
    memcpy(L2.mx,L1.mx,sizeof(L1.mx));
    while(x){
        if(x&1) L1=multi(L1,L2);
        L2=multi(L2,L2);
        x>>=1;
    }
    return L1.mx[(1<<m)-1][(1<<m)-1];//最後放滿,轉移到末狀態
}
int main()
{
    while(scanf("%d%d",&m,&n)==2){
        memset(L1.mx,0,sizeof(L1.mx));
        dfs(0,0,0);
        int ans=solve(n-1);
        printf("%d\n",ans);
    }
    return 0;
}
相關文章
相關標籤/搜索