luoguP6028算术 题解(推柿子+整除分块+调和级数)
题目
大意很好理解,给你一个肥常奇怪的柿子,求它的值。
30分做法(暴力):
显然通过题目给出的柿子本身就可以\(O(n)\)求\(f[i]\)然后再\(O(n)\)求和,可以得到一个\(O(n^2)\)的算法。
60分做法(大力推柿子):
通过一番鬼斧神工般的操作,成功把原柿子转化成\(\sum\limits_{d\mid n}^{d\leq n}\frac{1}{d}\)
转化过程如下:(正着推需要极其高超敏锐的数学直觉,所以我们倒着推)
最难的一步:\(\sum\limits_{d\mid n}\frac{1}{d}=\prod\limits_{i=1}^{pcnt}(\frac{1}{p_i^0}+\frac{1}{p_i^1}+\frac{1}{p_i^2}+……+\frac{1}{p_i^{cnt_i}})\)
这里的\(pcnt\)表示\(n\)所分解成的质因数的个数,\(p_i\)表示第i个质数,\(cnt_i\)表示第i个质数在n中有几个。
正确性:每一个约数一定都是n的质因子中选某些质因子的某些次方拼成的,满足一一对应,等式前面的是所有约数和,等式后面是所有质因子所有次方的可能组合方式的和(根据乘法分配率)。
接着往下推吧:
\(\prod\limits_{i=1}^{pcnt}(\frac{1}{p_i^0}+\frac{1}{p_i^1}+\frac{1}{p_i^2}+……+\frac{1}{p_i^{cnt_i}})=\prod\limits_{i=1}^{pcnt}\frac{p_i^0*(1-\frac{1}{p_i^{cnt_i+1}})}{1-\frac{1}{p_i}}\)
这一步是等比数列求和公式。
下面:
\(\prod\limits_{i=1}^{pcnt}\frac{p_i^0*(1-\frac{1}{p_i^{cnt_i+1}})}{1-\frac{1}{p_i}}=\prod\limits_{i=1}^{pcnt}\frac{\frac{p_i^{cnt_i+1}-1}{p_i^{cnt_i+1}}}{\frac{p_i-1}{p_i}}\)
\(\prod\limits_{i=1}^{pcnt}\frac{\frac{p_i^{cnt_i+1}-1}{p_i^{cnt_i+1}}}{\frac{p_i-1}{p_i}}=\prod\limits_{i=1}^{pcnt}\frac{p^{cnt_i+1}-1}{p^{cnt_i}*(p_i-1)}=\prod\limits_{i=1}^{pcnt}\frac{p^{cnt_i+1}-1}{p^{cnt_i+1}-p^{cnt_i}}\)
到这里,就是题目中给的柿子了,推完了……吗?
发现这个柿子还是没有优化到\(O(n)\)(对于每一个\(n\)需要枚举它的所有约数,这是\(O(n\sqrt n)\)的),还需要进一步优化
\(\sum\limits_{i=1}^n\sum\limits_{d\mid i}\frac{1}{d}=\sum\limits_{d=1}^n\sum\limits_{d\mid i}^{i\leq n}\frac{1}{d}\)
这一步我也不太会证,大概就是从实际意义上去考虑,枚举每一个\(i\),算一遍能整除它的\(d\),和枚举每一个\(d\),算一遍它能整除的\(i\),这样每一对\(d~i\)被计算的次数都是一样的,所以正确性应该没啥问题……
然后就是最后一步辣:
\(\sum\limits_{d=1}^n\sum\limits_{d\mid i}^{i\leq n}\frac{1}{d}=\sum\limits_{d=1}^n\lfloor\frac{n}{d}\rfloor*\frac{1}{d}\)
刚才那个柿子的第二个\(\sum\)显然就是找1~n里面有几个能被d整除的数,这个数量就是\(\lfloor\frac{n}{d}\rfloor\)
至于证明(我自己口胡的):\(\lfloor\frac{n}{d}\rfloor\)这个柿子的结果等于在\(n\)以内能被\(d\)整除的最大的数除以\(d\)的结果,就是\(n\)以内能被\(d\)整除的数的个数
这就是\(O(n)\)的了,直接跑一遍就OK
100分做法:(整除分块+调和级数)
考虑继续优化这个柿子:\(\sum\limits_{d=1}^n\lfloor\frac{n}{d}\rfloor*\frac{1}{d}\)
把这个柿子拆成两半考虑:
\(\sum\limits_{d=1}^n\lfloor\frac{n}{d}\rfloor*\frac{1}{d}=\sum\limits_{d=1}^n\lfloor\frac{n}{d}\rfloor*\sum\limits_{d=1}^n\frac{1}{d}\)
然后就显然发现前一半是整除分块,后一半是调和级数
恶补下这两个知识点:
- 整除分块:
要求形如\(\sum\limits_{d=1}^n\lfloor\frac{n}{d}\rfloor\)的柿子可以\(O(\sqrt n)\)求。
运用了在\(n\)以内,\(n\)除以很多数结果是一样的可以直接合并起来算,然后这些合并后的数大概级别是\(\sqrt n\)的,把每一堆结果相同的\(d\)归为「一块」,只算一遍。
具体操作:
根据定义对于每一个块的起点\(l\)和终点\(r\),有\(\lfloor\frac{n}{l}\rfloor=\lfloor\frac{n}{r}\rfloor\),而\(r\)作为这一块的最后一项,有性质\(\lfloor\frac{n}{\lfloor\frac{n}{r}\rfloor}\rfloor=r\),所以从左到右遍历时候,对于每一个\(l\),直接计算\((r-l+1)*\lfloor\frac{n}{l}\rfloor\)然后把\(l\)跳到\(r+1\),进到下一个块,就完了。 - 调和级数:
调和级数是形如\(1+\frac{1}{2}+\frac{1}{3}+\frac{1}{4}+……\)的一个发散的无穷级数。
上面的柿子中后一半\(\sum\limits_{d=1}^n\frac{1}{d}\)就是个调和级数的前n项。
关于调和级数有这样一个柿子:\(1+1/2+1/3+1/4+...1/n = ln(n+1) + r\),\(r\)是欧拉常数约等于0.5772156649(这个柿子是欧拉推的,不是我)
因为欧拉常数是个近似值,它会卡精度,所以我们可以预处理前\(1e7\)个答案的前缀和,剩下的用这个柿子求。
所以最后的答案是:\(\sum\limits_{d=1}^n\lfloor\frac{n}{d}\rfloor*\frac{1}{d}=\sum\limits_{每一个块的l,r}(r-l+1)*\lfloor\frac{n}{l}\rfloor*(\frac{1}{l}*\frac{1}{l+1}*\frac{1}{l+2}*……*\frac{1}{r})\)
对于每一个块,计算\((r-l+1)*\lfloor\frac{n}{l}\rfloor*(sum[r]/sum[l-1])\)的值,然后累加起来就是答案了。
ps:
通过这道题我昨天花了好长时间发现一个没啥用的小规律:
\(\frac{\sum\limits_{d\mid n} d}{n}=\sum\limits_{d\mid n}\frac{1}{d}\)
确实是对的可以证。
我是在看了题解后尝试把原柿子正着推回去的时候,经过另一个等比数列求和(\(1+p_i+p_i^2+p_i^3+……\)的和),变成了\(\frac{\sum\limits_{d\mid n} d}{n}\),我发现自己推柿子的过程没问题,所以猜测这俩柿子是相等的,然后发现真是相等的。