一條長爲 \(n\) 的數軸,能夠從任意整點 \(\in [1, n]\) 出發,假設當前在 \(x\) ,下一步能到達的點 \(y\) 須要知足,\(y\) 從未到過,且 \(1 \le y \le x + m\) ,問長剛好爲 \(k\) 的合法路徑條數。c++
對於 \(F1\) 有 \(1 \le n \le 10^5, 1 \le k \le \min(n, 12), 1 \le m \le 4\)git
對於 \(F2\) 有 \(1 \le n \le 10^9\) 。優化
比較 \(\text{tricky}\) 的一個題。ui
考慮咱們當前假設通過的路徑爲 \(v_1, v_2, \cdots, v_p\) ,咱們當前能夠添加一個 \(x < \min_{i = 1}^{p} \{v_i\}\) 。顯然咱們是必定能夠添加到隊尾的,其次咱們能夠添加到那些 \(v_i \le x + m\) 的前面。spa
那麼咱們就獲得一個很顯然的 \(dp\) 了,考慮從大到小依次考慮每一個數填仍是不填就能輕鬆轉移了。debug
具體來講設 \(dp[i][j][sta]\) 爲當前在第 \(i\) 個位置,路徑長度爲 \(j\) ,最後 \(m\) 個位置狀壓後的狀態爲 \(sta\) 。code
每次轉移的時候,若是不填直接轉過去,填的話能夠轉到後 \(m\) 個有 \(1\) 的狀態以及隊尾,也就是 \(1 + bitcount(sta)\) 。get
這樣 \(dp\) 恰好每條路都能一一對應上。it
對於 \(F1\) 直接 \(\mathcal O(nk2^m)\) 就好了,\(F2\) 考慮利用矩陣快速冪優化到 \(\mathcal O((k2^m)^3 \log n)\) 。(說實話 \(F2\) 沒啥意思。。)class
#include <bits/stdc++.h> #define For(i, l, r) for (register int i = (l), i##end = (int)(r); i <= i##end; ++i) #define Fordown(i, r, l) for (register int i = (r), i##end = (int)(l); i >= i##end; --i) #define Rep(i, r) for (register int i = (0), i##end = (int)(r); i < i##end; ++i) #define Set(a, v) memset(a, v, sizeof(a)) #define Cpy(a, b) memcpy(a, b, sizeof(a)) #define debug(x) cout << #x << ": " << (x) << endl using namespace std; template<typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; } template<typename T> inline bool chkmax(T &a, T b) { return b > a ? a = b, 1 : 0; } inline int read() { int x(0), sgn(1); char ch(getchar()); for (; !isdigit(ch); ch = getchar()) if (ch == '-') sgn = -1; for (; isdigit(ch); ch = getchar()) x = (x * 10) + (ch ^ 48); return x * sgn; } void File() { #ifdef zjp_shadow freopen ("F1.in", "r", stdin); freopen ("F1.out", "w", stdout); #endif } const int N = 1e5 + 1e3, K = 14, M = 4, Mod = 1e9 + 7; int dp[N][K][1 << M]; int main() { File(); int n = read(), k = read(), m = read(); dp[0][0][0] = 1; Rep (i, n) For (j, 0, k) Rep (sta, 1 << m) { (dp[i + 1][j][sta >> 1] += dp[i][j][sta])%= Mod; int res = dp[i][j][sta] * (1ll + __builtin_popcount(sta)) % Mod; (dp[i + 1][j + 1][(sta >> 1) | (1 << m - 1)] += res) %= Mod; } int ans = 0; Rep (sta, 1 << m) (ans += dp[n][k][sta]) %= Mod; printf ("%d\n", ans); return 0; }