\[\large\texttt
\]hydrooj 每日將從 hydrooj 主題庫及各大域中選出一題附以詳解在此處分享給各位使用者。
[coci2016-2017 contest#7 t6] kl**ir
題目傳送門
首先讀懂題意,我們發現,對於當前正在彈奏的一段樂曲,有以下兩種情況:
第二種情況比較簡單,對於第二種情況,那麼有:
\[dp_i=dp_+\frac+\frac\times(dp_i-dp_1+1)+\frac\times(dp_i+1)
\]\[\rightarrow dp_i=n\times dp_
\]其中,第乙個 \(\frac\) 表示第 \(i\) 個音符直接彈奏正確的期望,\(\frac\times(dp_i-dp_1+1)\) 表示這個音符彈奏錯誤,但與第乙個音符相同的期望,\(\frac\times(dp_i+1)\) 表示這個音符彈奏錯誤,同時與第乙個音符不同的期望。
樣例三對應的就是這種情況。
3
31 2 3
3
927
接下來討論第一種情況。
前字尾顯然可以用 kmp 預處理處理。
設已經彈奏了 \(1\to i\),現在要彈奏第 \(i+1\) 個音符。列舉當前彈奏音符 \(j\)。彈錯時,需要找到最長的已經彈對的字首,記為 \(k_j\),於是有:
\[dp_=dp_i+\frac+\frac\times\sum\limits_^n(dp_-dp_+1)(j\neq a_)
\]\[\rightarrow dp_=dp_i+n+\sum\limits_^n(dp_-dp_)(j\neq a_)
\]其中 \(\frac\times\sum\limits_^n(dp_-dp_+1)(j\neq a_)\) 表示彈錯了,但已經彈對字首 \(1\to k\),接著從 \(k+1\) 彈到 \(n+1\) 的期望。兩層迴圈跑一下就完了。時間複雜度 \(\mathcal(n\times m^2)\),實測可過(大概是機子跑得快的原因)。
dp[1] = n;
f(i, 1, m)
}dp[i + 1] = (s + n + dp[i]) % mod;
}
雖然可過,但理論上還是蠻卡的。接下來我們考慮優化。
我們記當前為第 \(i\) 個音符,下乙個音符是 \(j\) 時,最終跳到的位置為 \(f_\),那麼 \(f_\) 和 \(f_\) 只有在 \(j=a_\) 時是不同的。因此對於 \(dp_\) 可以直接繼承 \(dp_}\) 的答案,再額外計算 \(j=a_\) 的貢獻即可。從上面方法中,可以看出 \(j=a_\) 的貢獻就是 \(n^\)。
綜上可得:
\[dp_i=dp_+n^i
\]時間複雜度 \(\mathcal(m)\),算是十分優秀了。
#include #define reg register
#define ll long long
#define _min(x, y) ((x) < (y) ? (x) : (y))
#define _max(x, y) ((x) > (y) ? (x) : (y))
#define min(x, y) ((x) > (y) and ((x) = (y)))
#define max(x, y) ((x) < (y) and ((x) = (y)))
#define f(i, a, b) for (reg int i = (a); i <= (b); ++i)
#define pf(i, a, b) for (reg int i = (a); i >= (b); --i)
#define for(i, x) for (reg int i = head[(x)]; i; i = net[(i)])
using namespace std;
bool beginning;
inline int read();
const int n = 1e6 + 5, mod = 1e9 + 7;
int n, m, a[n], fail[n];
inline void init()
}bool ending;
int main()
init();
int t = n;
f(i, 1, m)
return 0;
}inline int read()
while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
return f ? x : -x;
}
macesuted 提供優化思路。/bx
LeetCode每日一題 003 盛最多水的容器
想法一 盛水最多,即左右兩邊中間區域的矩形面積最大,稱左側為a邊,右側為b邊。比較直觀的解法是,固定某一邊 如a邊 依次比較b邊選取哪乙個所框住區域面積最大。因此,可以比較選取不同a邊所能框住面積的最大值,從而得到所有可能情況的最大值,及窮舉法。可通過雙層迴圈求解。想法二 在想法一基礎上,思考固定a...
每日一題 1
題目詳情 peter喜歡玩數字遊戲,但數獨這樣的遊戲對他來說太簡單了,於是他準備玩乙個難的遊戲。遊戲規則是在乙個n n的 裡填數,規則 對於每個輸入的n,從左上角開始,總是以對角線為起點,先橫著填,再豎著填。這裡給了一些樣例,請在樣例中找到規律並把這個n n的 列印出來吧。輸入描述 多組測試資料 資...
每日一題2018 3 21
leetcode 2 模擬十進位制運算考察單鏈表基本操作。題無難點,個人基礎需要提高。definition for singly linked list.struct listnode class solution while p while q if shi val s next null ret...