前言
本文章將會持續更新,主要是一些個人覺得比較妙的題,主觀性比較強(給自己記錄用的),有講錯請補充。
帶 !號的題是基礎例題,帶 * 號的是推薦首先完成的題(有一定啟發性的)。
組合數
P6620 [省選聯考 2020 A 卷] 組合數問題
運用斯特林數好的例題,普通冪轉下降冪。用到第二類斯特林數。
下降冪處理方式:先轉為階乘形式,後轉為組合數形式。如
這題按照題目推式子,主要卡點就是斯特林數的運用。
*高橋君
組合數與資料結構的結合。
離線詢問+ (\(n=10^{5}\)) 的資料範圍可以聯想到莫隊。
又透過歸納恆等式可以推出 \(n,k\) 分別左移或右移的式子。
注意莫隊的正確寫法,\(n,k\)的大小關係。
Lonely Mountain Dungeons
首先貪心,每個種族平均分肯定是更優的,所以先設分成 \(k\) 組,設 \(y=\dfrac{c_i}{k}\) 向下取整,\(y_1=\dfrac{c_i}{k}\) 向上取整,\(mod=c_i\% k\),那每個種族可以分出:
暴力求時間複雜度報表,分為三種方法最佳化方法了。
方法1:三分法。
上式化簡下來一定是關於 \(k\) 的二次函式,顯然隨著 \(k\) 的增大,值先增大,後減小,是個單峰函式(可以打表試試)。
然後普通三分就可以了。
方法2:差分字首和法(也是官方題解的方法)
定義 \(f[k]\) 為分為 \(k\) 個小組的最大方案。
可以發現當 \(k>c_i\) 時,當前種族的值是不變的。
\(\sum c_i\) 是 \(2\times 10^5\),所以遍歷所有 \(1\) 到 \(n\),讓 \(f[j]\) 加上每個種族的貢獻。因為當 \(i\) 超過 \(c[j]\) 時,後面的值不變,所以用差分來處理。
for(int i=1;i<=n;i++)
{
for(int j=1;j<c[i];j++)
f[j]+=get(i,j)*b,f[j+1]-=get(i,j)*b;
f[c[i]]+=get(i,c[i])*b;
}
最後遍歷小組數即可。
方法3:
與上中方法類似,我們知道 $k $ 一定不大於 \(maxc\),按 \(c\) 的大小從小到大排序,從 \(2\) 到 \(n\) 列舉小組數,小於 \(i\) 的種族就暴力計算,大於的因為值都不變了,拿一個陣列記錄一下字首即可。
時間複雜度可以證明不超過 \(O(n \sqrt {\sum c})\)