luoguP6028算术 题解(推柿子+整除分块+调和级数)

题目
大意很好理解,给你一个肥常奇怪的柿子,求它的值。
30分做法(暴力):
显然通过题目给出的柿子本身就可以(O(n))(f[i])然后再(O(n))求和,可以得到一个(O(n^2))的算法。
60分做法(大力推柿子):
通过一番鬼斧神工般的操作,成功把原柿子转化成(sumlimits_{dmid n}^{dleq n}frac{1}{d})
转化过程如下:(正着推需要极其高超敏锐的数学直觉,所以我们倒着推)
最难的一步:(sumlimits_{dmid n}frac{1}{d}=prodlimits_{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的质因子中选某些质因子的某些次方拼成的,满足一一对应,等式前面的是所有约数和,等式后面是所有质因子所有次方的可能组合方式的和(根据乘法分配率)。
接着往下推吧:
(prodlimits_{i=1}^{pcnt}(frac{1}{p_i^0}+frac{1}{p_i^1}+frac{1}{p_i^2}+……+frac{1}{p_i^{cnt_i}})=prodlimits_{i=1}^{pcnt}frac{p_i^0*(1-frac{1}{p_i^{cnt_i+1}})}{1-frac{1}{p_i}})
这一步是等比数列求和公式。
下面:
(prodlimits_{i=1}^{pcnt}frac{p_i^0*(1-frac{1}{p_i^{cnt_i+1}})}{1-frac{1}{p_i}}=prodlimits_{i=1}^{pcnt}frac{frac{p_i^{cnt_i+1}-1}{p_i^{cnt_i+1}}}{frac{p_i-1}{p_i}})
(prodlimits_{i=1}^{pcnt}frac{frac{p_i^{cnt_i+1}-1}{p_i^{cnt_i+1}}}{frac{p_i-1}{p_i}}=prodlimits_{i=1}^{pcnt}frac{p^{cnt_i+1}-1}{p^{cnt_i}*(p_i-1)}=prodlimits_{i=1}^{pcnt}frac{p^{cnt_i+1}-1}{p^{cnt_i+1}-p^{cnt_i}})
到这里,就是题目中给的柿子了,推完了……吗?
发现这个柿子还是没有优化到(O(n))(对于每一个(n)需要枚举它的所有约数,这是(O(nsqrt n))的),还需要进一步优化
(sumlimits_{i=1}^nsumlimits_{dmid i}frac{1}{d}=sumlimits_{d=1}^nsumlimits_{dmid i}^{ileq n}frac{1}{d})
这一步我也不太会证,大概就是从实际意义上去考虑,枚举每一个(i),算一遍能整除它的(d),和枚举每一个(d),算一遍它能整除的(i),这样每一对(d~i)被计算的次数都是一样的,所以正确性应该没啥问题……
然后就是最后一步辣:
(sumlimits_{d=1}^nsumlimits_{dmid i}^{ileq n}frac{1}{d}=sumlimits_{d=1}^nlfloorfrac{n}{d} floor*frac{1}{d})
刚才那个柿子的第二个(sum)显然就是找1~n里面有几个能被d整除的数,这个数量就是(lfloorfrac{n}{d} floor)
至于证明(我自己口胡的):(lfloorfrac{n}{d} floor)这个柿子的结果等于在(n)以内能被(d)整除的最大的数除以(d)的结果,就是(n)以内能被(d)整除的数的个数
这就是(O(n))的了,直接跑一遍就OK
100分做法:(整除分块+调和级数)
考虑继续优化这个柿子:(sumlimits_{d=1}^nlfloorfrac{n}{d} floor*frac{1}{d})
把这个柿子拆成两半考虑:
(sumlimits_{d=1}^nlfloorfrac{n}{d} floor*frac{1}{d}=sumlimits_{d=1}^nlfloorfrac{n}{d} floor*sumlimits_{d=1}^nfrac{1}{d})
然后就显然发现前一半是整除分块,后一半是调和级数
恶补下这两个知识点:

  1. 整除分块:
    要求形如(sumlimits_{d=1}^nlfloorfrac{n}{d} floor)的柿子可以(O(sqrt n))求。
    运用了在(n)以内,(n)除以很多数结果是一样的可以直接合并起来算,然后这些合并后的数大概级别是(sqrt n)的,把每一堆结果相同的(d)归为「一块」,只算一遍。
    具体操作:
    根据定义对于每一个块的起点(l)和终点(r),有(lfloorfrac{n}{l} floor=lfloorfrac{n}{r} floor),而(r)作为这一块的最后一项,有性质(lfloorfrac{n}{lfloorfrac{n}{r} floor} floor=r),所以从左到右遍历时候,对于每一个(l),直接计算((r-l+1)*lfloorfrac{n}{l} floor)然后把(l)跳到(r+1),进到下一个块,就完了。
  2. 调和级数:
    调和级数是形如(1+frac{1}{2}+frac{1}{3}+frac{1}{4}+……)的一个发散的无穷级数。
    上面的柿子中后一半(sumlimits_{d=1}^nfrac{1}{d})就是个调和级数的前n项。
    关于调和级数有这样一个柿子:(1+1/2+1/3+1/4+...1/n = ln(n+1) + r)(r)是欧拉常数约等于0.5772156649(这个柿子是欧拉推的,不是我)
    因为欧拉常数是个近似值,它会卡精度,所以我们可以预处理前(1e7)个答案的前缀和,剩下的用这个柿子求。

所以最后的答案是:(sumlimits_{d=1}^nlfloorfrac{n}{d} floor*frac{1}{d}=sumlimits_{每一个块的l,r}(r-l+1)*lfloorfrac{n}{l} floor*(frac{1}{l}*frac{1}{l+1}*frac{1}{l+2}*……*frac{1}{r}))
对于每一个块,计算((r-l+1)*lfloorfrac{n}{l} floor*(sum[r]/sum[l-1]))的值,然后累加起来就是答案了。
ps:
通过这道题我昨天花了好长时间发现一个没啥用的小规律:
(frac{sumlimits_{dmid n} d}{n}=sumlimits_{dmid n}frac{1}{d})
确实是对的可以证。
我是在看了题解后尝试把原柿子正着推回去的时候,经过另一个等比数列求和((1+p_i+p_i^2+p_i^3+……)的和),变成了(frac{sumlimits_{dmid n} d}{n}),我发现自己推柿子的过程没问题,所以猜测这俩柿子是相等的,然后发现真是相等的。

原文地址:https://www.cnblogs.com/liu-yi-tong/p/13904334.html