1. 程式人生 > 其它 >計算索引為10的斐波那契數列對應的值

計算索引為10的斐波那契數列對應的值

整除分塊學習筆記

值域分段求和

假如我們要對這樣的式子進行求和:

\[\sum\limits_{i=1}^{n} 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_{i=1}^{m}(R_i-L_i+1)v_i \]

例如:

\[\sum\limits_{i=1}^{n}\lfloor{log_2i}\rfloor \]

\(f(i)=\lfloor{log_2i}\rfloor\),容易發現 \(0\le f(i) \le log_2n\) 且單調遞增。運用上述方法,可計算出 \(L_x=2^x,R_x=2^{x+1}-1\),於是可以在 \(O(logn)\) 的時間內求解:

\[Ans=\sum\limits_{i=1}^{\lfloor{log_2(n)}\rfloor}2^ii \]

整除分塊

整除分塊就是 依據整除的性質,對取值種類只有 \(\sqrt n\) 級別的 \(f\) 序列進行的值域分段求和

舉幾個簡單的例子:


\[\sum\limits_{i=1}^{n}\lfloor{\frac{n}{i}}\rfloor \]

\(f(i)=\lfloor{\frac{n}{i}}\rfloor\),則 \(f(i)\) 的取值不超過 \(2\sqrt n\) 種且單調遞增。運用上述方法,可計算出 \(L_x=\lfloor\frac{n}{\lfloor\frac{n}{x-1}\rfloor}\rfloor+1,R_x=\lfloor\frac{n}{\lfloor\frac{n}{x}\rfloor}\rfloor\),值域分段求和即可,時間複雜度 \(O(\sqrt{n})\)

程式碼片段:

for(int l=1,r=0; l<=n;) {
        l=r+1,r=n/(n/l);
        ans+=(n/l)*(r-l+1);
}

\[\sum\limits_{i=1}^{n}i^2\lfloor{\frac{n}{i}}\rfloor \]

\(f(i)=\lfloor{\frac{n}{i}}\rfloor\),仍然有 \(L_x=\lfloor\frac{n}{\lfloor\frac{n}{x-1}\rfloor}\rfloor+1,R_x=\lfloor\frac{n}{\lfloor\frac{n}{x}\rfloor}\rfloor\)。考慮對於每一段 \([L_x,R_x]\) 計算答案的貢獻:

\(\sum\limits_{i=L_x}^{R_x}i^2x\)

\(=x\sum\limits_{i=L_x}^{R_x}i^2\)

\(=x(\sum\limits_{i=1}^{R_x}i^2-\sum\limits_{i=1}^{L_x-1}i^2)\)

\(=x(\frac{R_x(R_x+1)(2R_x+1)}{6}-\frac{L_x(L_x+1)(2L_x+1)}{6})\)

然後就可以 \(O(\sqrt n)\) 求解了。

程式碼片段:

for(int l=1,r=0; l<=n;) {
        l=r+1,r=n/(n/l);
        ans+=(n/l)*((r*(r+1)*(r<<1|1)/6-l*(l+1)*(l<<1|1)/6);
}

習題: