假如我們要對這樣的式子進行求和:
\[\sum\limits_^ f(i)
\]如果 \(f(i)\) 的取值有限,只有 \(m\) 個,且對於所有的 \(f(i)=x\) 在序列中都是連續的一段,那麼就可以進行值域分段求和。
找出每個取值 \(x\) 在原序列中的第一次出現的位置 \(l_x\) 和最後一次出現的位置 \(r_x\),可以在 \(o(m)\) 的時間內算出答案(設 \(v_1,v_2\dots v_m\) 為 \(f(i)\) 的 \(m\) 種取值):
\[ans=\sum\limits_^(r_i-l_i+1)v_i
\]例如:
\[\sum\limits_^\lfloor\rfloor
\]設 \(f(i)=\lfloor\rfloor\),容易發現 \(0\le f(i) \le log_2n\) 且單調遞增。運用上述方法,可計算出 \(l_x=2^x,r_x=2^-1\),於是可以在 \(o(logn)\) 的時間內求解:
\[ans=\sum\limits_^\rfloor}2^ii
\]整除分塊就是依據整除的性質,對取值種類只有 \(\sqrt n\) 級別的 \(f\) 序列進行的值域分段求和。
舉幾個簡單的例子:
\[\sum\limits_^\lfloor}\rfloor
\]設 \(f(i)=\lfloor}\rfloor\),則 \(f(i)\) 的取值不超過 \(2\sqrt n\) 種且單調遞增。運用上述方法,可計算出 \(l_x=\lfloor\frac\rfloor}\rfloor+1,r_x=\lfloor\frac\rfloor}\rfloor\),值域分段求和即可,時間複雜度 \(o(\sqrt)\)。
**片段:
for(int l=1,r=0; l<=n;)
\[\sum\limits_^i^2\lfloor}\rfloor
\]設 \(f(i)=\lfloor}\rfloor\),仍然有 \(l_x=\lfloor\frac\rfloor}\rfloor+1,r_x=\lfloor\frac\rfloor}\rfloor\)。考慮對於每一段 \([l_x,r_x]\) 計算答案的貢獻:
\(\sum\limits_^i^2x\)
\(=x\sum\limits_^i^2\)
\(=x(\sum\limits_^i^2-\sum\limits_^i^2)\)
\(=x(\frac-\frac)\)
然後就可以 \(o(\sqrt n)\) 求解了。
**片段:
for(int l=1,r=0; l<=n;)
習題: 整除分塊學習筆記
其實一直沒有把整除分塊看成乙個演算法,只看成乙個思維。然後發現我不會思維了,於是來補一下學習筆記。看一道例題 uva11526 就是求 sum limits 我們發現很多值都是一樣的,所以可以快速計算掉。具體的,我們發現 i 到 frac 內所有數是一樣的。那麼就可以 o sqrt n 計算了。但是...
整除分塊 學習筆記
hgoi20181027模擬題 給定n,m,快速求出 fht n,m 1e9 7 的值。對於100 的資料 n,m 1,000,000,000 然後為了這個問題我們去找了整除分塊的演算法 對於g n,k 化簡 顯然 a b a a b b 在c 中floor a b a b 所以我們打個表來看看k ...
整除分塊 學習筆記
板子題 uva11526 題目大意 給定乙個 n 求 sum limits lfloor frac rfloor 其中 n 為 32 位無符號整數。顯然如果暴力求解肯定是不可行的,顯然會 tle,所以我們需要找一種複雜度更優的演算法。我們可以先令 n 10 觀察一下函式 operatorname x...