1. 程式人生 > 其它 >【演算法學習筆記】分段打表

【演算法學習筆記】分段打表

前置知識:分塊

樸素的打表,指的是在比賽時把所有可能的輸入對應的答案都計算出來並儲存下來,然後在程式碼裡開個陣列把答案放裡面,直接輸出即可。

注意這個技巧只適用於輸入的值域不大(如,輸入只有一個數,而且範圍很小)的問題,否則可能會導致程式碼過長、MLE、打表需要的時間過長等問題。

Sample Description

規定 $f(x)$ 為整數 $x$ 的二進位制表示中 $1$ 的個數。輸入一個正整數 $n$($n\leq 10^9$),輸出 $\sum_{i=1}^n f^2(i)$。


如果對於每一個 \(n\),都輸出 \(f(n)\) 的話,除了可能會 MLE 外,還有可能程式碼超過最大程式碼長度限制,導致編譯不通過。

我們考慮優化這個答案表。採用 分塊 的思想,我們設定一個合理的步長 \(m\)(這個步長一般視程式碼長度而定),對於第 \(i\)​ 塊,計算出:

\[\sum_{k=\frac{n}{m}(i-1)+1}^{\frac{ni}{m}} f^2(k) \]

的值。

然後輸出答案時採用分塊思想處理即可。即,整塊的答案用預處理的值計算,非整塊的答案暴力計算。

一般來說,這樣的問題對於處理單個函式值 \(f(x)\) 很快,但是需要大量函式值求和(求積或某些可以快速合併的操作),列舉會超出時間限制,在找不到標準做法的情況下,分段打表是一個不錯的選擇。

注意事項

當上題中指數不是定值,但是範圍較小,也可以考慮打表。


例題

「BZOJ 3798」特殊的質數:求 \([l,r]\) 區間內有多少個質數可以分解為兩個正整數的平方和。

「Luogu P1822」魔法指紋

The desire of his soul is the prophecy of his fate
你靈魂的慾望,是你命運的先知。