矩陣乘 Shoi2013 超級跳馬

2021-08-09 20:23:20 字數 1449 閱讀 8264

問題 f: [shoi2013]超級跳馬

時間限制: 1 sec 記憶體限制: 256 mb

題目描述

現有乙個n行m列的棋盤,乙隻馬欲從棋盤的左上角跳到右下角。每一步它向右跳奇數列,且跳到本行或相鄰行。跳越期間,馬不能離開棋盤。例如,當n = 3, m = 10時,下圖是一種可行的跳法。

試求跳法種數mod 30011。

輸入 僅有一行,包含兩個正整數n, m,表示棋盤的規模。

輸出 僅有一行,包含乙個整數,即跳法種數mod 30011。

樣例輸入

3 5

樣例輸出

10 提示

對於100%的資料,1 ≤ n ≤ 50,2 ≤ m ≤ 10^9

看資料範圍就知道是矩陣乘。。。

轉移是要分奇數列和偶數列的,但實際上並沒有那麼麻煩。

對於這個方格

紅格的方案應該從所有的黃格轉移過來的,可以發現,藍格其實是其他黃格的字首和。所以紅格方案數=靠近自己的三個黃格方案數+兩排前對應那個格的方案數。

因此只要記錄兩列的方案數即可。轉移矩陣我寫成了這樣,

初始矩陣上面n行表示這一列的狀態,下面n行表示上一列的狀態。

但是還有乙個問題。在第三列時,會額外加一次第一行第一列的那個1。而那個1是被我們當作字首和加上去的。實際上並沒有那個字首和啊,我們並沒有跳一步到達1.因此相當於在第三列第一行多了乙個1.去掉的方法有很多,大部分都是再乘一邊什麼的,我yy出了一種方法:在第3列最上多了乙個1,跑到第m列產生的方案數,等於從第一列有乙個1,跑到第m-2列的方案數。而我們求m列第n行的方案實際上是f[m-1][n]+f[m-1][n-1]+f[m-2][n]的。那麼f[m-2][n]恰好就是多出來的方案數。不把他加上去就就成了。

#include 

#include

#include

#include

#define mod 30011

#define ll long long

using

namespace

std;

int n,m,sz;

struct node

friend node operator *(node a,node b)

}ans,a,b;

int main()

for(int i=0;i1;

for(;m;m>>=1,b=b*b)if(m&1)ans=ans*b;

a=ans*a;

printf("%lld\n",(a.f[n-1][0]+a.f[n-2][0])%mod);

}

SHOI2013 超級跳馬

我是常年遊蕩於題解區的幽靈。直觀的想法就是字首和 差分優化dp,但還有些比較奇妙的方法or trick f i j f i 1 j 1 f i 1 j f i 1 j 1 color 因為可以一步跳到 f i j 的狀態也可以一步跳到 f i 2 j 反過來也成立 只考慮從左邊某個特定的列的轉移矩陣...

bzoj 4417 Shoi2013 超級跳馬

題意 現有乙個n行m列的棋盤,乙隻馬欲從棋盤的左上角跳到右下角。每一步它向右跳奇數列,且跳到本行或相鄰行。試求跳法種數mod 30011。題解 dp 矩陣乘法 快速冪 設f i j 表示走到第2i 1列,第 j 行的方案數,g i j 表示走到第2i 列,第j行的方案數。那麼f i j k 1i 1...

SHTSC2013 超級跳馬 矩陣快速冪

僅有一行,包含兩個正整數n,m,表示棋盤的規模。output 僅有一行,包含乙個整數,即跳法種數mod 30011。sample input 3 5sample output 10data constraint 對於10 的資料,1 n 10,2 m 10 對於50 的資料,1 n 10,2 m 1...