我是常年遊蕩於題解區的幽靈。
直觀的想法就是字首和+差分優化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]\), 反過來也成立 。
只考慮從左邊某個特定的列的轉移矩陣, 設為 \(j\), 設第 \(i\) 列的答案矩陣是 \(a_i\), 則有:\(a_n = j*(a_+a_+a_+\cdots)\) 且 \(a_ = j*(a_+a_+a_+\cdots)\), 不難得出 \(a_n = j*a_+a_\), 這也是個遞推, 構造矩陣:
\[[ \begin
j & e\\
e & o
\end
] *[ \begin
a_n\\
a_ \end
]=[\begin
a_\\
a_ \end
]\]其中 \(e\) 是單位矩陣而 \(o\) 是全零矩陣,就可以大力遞推了。
這個, 建圖
接下來選擇性地實現/口胡上述的某些解法(我挺中意矩陣套矩陣的解法)
目錄s0[i]
維護與當前列差偶數列的第i
行的方案數之和,s1[i]
則是相差奇數列的。
s1[i] <- s0[i]
#includeusing namespace std;
const int mo = 30011;
int n,m;
int qm(int x)
struct m
};m operator*(const m &a, const m &b)
m operator+(const m &a, const m &b)
struct m2 s,t,delta;
m2 operator*(const m2 &a, const m2 &b)
int main()
m -= 3;
delta = t;
while(m)
s = delta*s;
printf("%d",s.t[1][1].t[n][1]);
return 0;
}
矩陣乘 Shoi2013 超級跳馬
問題 f shoi2013 超級跳馬 時間限制 1 sec 記憶體限制 256 mb 題目描述 現有乙個n行m列的棋盤,乙隻馬欲從棋盤的左上角跳到右下角。每一步它向右跳奇數列,且跳到本行或相鄰行。跳越期間,馬不能離開棋盤。例如,當n 3,m 10時,下圖是一種可行的跳法。試求跳法種數mod 3001...
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...
SHOI2013 扇形面積並
補一張圖 我們嘗試把圓上的扇形轉化成直線上的矩形 我們維護 1,2m 的區間,那麼每個能產生貢獻的子區間的長度第k大的半徑的平方的總和就是answer了。怎麼轉化呢?左端點為a1 m 1,右端點為a2 m。為什麼要 m?因為原先的範圍是 m,m 的,所以整體右移。為什麼左端點要 1?因為我們維護的是...