标签:前缀 limits int sum 复杂度 Dircliet 我们
以下若无特殊说明,皆认为 \(a_i\) 已知,\(b_i\) 非已知。
前缀和
设有:
\[ b_n=\sum\limits_{i|n}a_i \]显然通过枚举我们可以用 \(O(\sum\left\lfloor \frac{n}{i} \right\rfloor=n\log n)\) 的时间复杂度来做这个事情。我们考虑有没有更为优秀的算法。
根据唯一分解定理,我们有:
\[ n=\prod p_i^{\alpha_i} \]那么其实我们可以用 \((\alpha_1,\alpha_2,...)\) 去表示 \(n\)。所以上面的这些东西我们可以看做是一个高维的前缀和。类比做二维前缀和我们可以先通过对第一维做前缀和然后再对第二维做前缀和得到,高维前缀和我们可以通过对每一维做前缀和的得到最终结果。
代码
for(int i=1;i<=tail&&Prime[i]<=n;i++)
for(int j=1;j*Prime[i]<=n;j++) a[j*Prime[i]]+=a[j];
不难发现复杂度和埃氏筛的复杂度相同,为 \(O(n\log n)\)
Dirchlet 后缀和
我们需要求
\[ b_i=\sum\limits_{i|n}a_n \]显然做后缀和只需要把刚刚那个反过来做就可以。
for(int i=1;i<=tail&&Prime[i]<=n;i++)
for(int j=n/Prime[i];j>=1;j--) a[j]+=a[j*Prime[i]];
倒推 Dirichlet 前缀和
\[ a_n=\sum\limits_{i|n}b_i \]这就相当于告诉我们前缀和结果让我们求每一个位置的元素,我们类比二维前缀和做法,不难得出结论。
for(int i=1;i<=tail$$Prime[i]<=n;i++)
for(int j=n/Prime[i];j>=1;j--) a[j*Prime[i]]-=a[j];
倒推 Dirichlet 前缀和
\[ a_i=\sum\limits_{i|n}b_n \]
for(int i=1;i<=tail&&Prime[i]<=n;i++)
for(int j=1;j*Prime[i]<=n;j++) a[j*Prime]
只要把这个东西高维前缀和的本质说清楚了,其余就很好理解。
标签:前缀,limits,int,sum,复杂度,Dircliet,我们 来源: https://www.cnblogs.com/TianMeng-hyl/p/15829088.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。