杜教筛

浅谈一类积性函数的前缀和 - skywalkert's space - CSDN博客

杜教筛可以在\(O(n^{\frac 23})\)的时间复杂度内利用卷积求出一些积性函数的前缀和.

算法

给定\(f(n)\), 现要求\(S(n)=\sum_{i=1}^n f(i)\).

定义卷积运算 \((f*g)(n) = \sum_{d | n} f(d) g(\frac{n}{d})\).

如果存在\(g(n)\), 满足\(f*g=h\), 且\(g\)和\(h\)都能 \(O(1)\) 求出前缀和, 我们可以较快地求出\(S(n)\).

注意到

\[\begin{aligned}
\sum\limits_{i=1}^{n}(f*g)(i) &= \sum\limits_{i=1}^{n} \sum \limits _{d|i} f(d)g(\frac{i}{d}) \\
&= \sum \limits _{d=1}^{n} g(d)\sum\limits _{i=1}^{\lfloor \frac{n}{d}\rfloor } f(i) \\
&= \sum \limits _{d=1}^{n} g(d) S(\lfloor \frac{n}{d} \rfloor) \end{aligned}
\]

因此, 有

\[g(1)S(n)=\sum\limits_{i=1}^{n}(f*g)(i) - \sum \limits _{i=2}^{n} g(i) S(\lfloor \frac{n}{i} \rfloor)
\]

可以递归(并记忆化)下去.

对于复杂度: 展开一层递归, 通过积分可以求出时间复杂度为 \(O(n^{\frac 34})\).

如果预处理前 \(m\) 个答案, 利用同样的方法可以得到复杂度为 \(O(m + \frac n{\sqrt m})\), 当 \(m = n^{\frac 23}\) 时取最小值为 \(O(n^{\frac 23})\).

并不知道为什么算复杂度时可以只展开一层

Upd: 关于为什么算复杂度时只展开一层:

递归的 \(x\) 显然为 \(\lfloor \frac ni \rfloor\) 的形式, 可以通过哈希表(或者下面的另一种方法)存储. 那么递归到第二层的时候会发现要求的值已经求过了, 因此只需展开一层就行了.

关于卷积

显然, 卷积运算满足交换律和结合律, 可以推式子验证一下.

另外, 积性函数的卷积仍然为积性函数.

定义函数 \(\epsilon(n) = [n=1], I(n) = 1, id(n) = n\), 有

\[f * \epsilon = f
\]

这是\(\epsilon\)函数的定义.

\[\phi * I = id
\]

\[\mu * I = \epsilon
\]

这是莫比乌斯函数的定义.

\[\mu * id = \phi
\]

\[id * id = id \cdot d
\]

\[(\phi \cdot id) * id = id^2
\]

Problem Description

求 \(\phi (n)\) 和 \(\mu (n)\) 的前缀和. \(1 \le n \le 2^{31}-1\).

Code

另外, 卡常数...

用long long会TLE, 改成unsigned int就不会.

似乎不少毒瘤数论题都卡常

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cmath>
  4. #include<cstring>
  5. #include<algorithm>
  6. #include<set>
  7. #include<map>
  8. #include<unordered_map>
  9. using namespace std;
  10. #define rep(i,l,r) for(register int i=(l);i<=(r);++i)
  11. #define repdo(i,l,r) for(register int i=(l);i>=(r);--i)
  12. #define il inline
  13. typedef double db;
  14. typedef long long ll;
  15. typedef unsigned long long ull;
  16. typedef unsigned int uint;
  17. //---------------------------------------
  18. const int blsz=5e6+50,sqsz=5e4+50;
  19. ll bnd=5e6;
  20. ll t,n;
  21. int nopr[blsz],pr[blsz],pp=0;
  22. ll mu[blsz],phi[blsz];
  23. void init(){
  24. nopr[1]=mu[1]=phi[1]=1;//a
  25. rep(i,2,bnd){
  26. if(nopr[i]==0)pr[++pp]=i,mu[i]=-1,phi[i]=i-1;//b
  27. rep(j,1,pp){
  28. if(i*pr[j]>bnd)break;
  29. nopr[i*pr[j]]=1;
  30. if(i%pr[j])mu[i*pr[j]]=-mu[i],phi[i*pr[j]]=phi[i]*phi[pr[j]];
  31. else{mu[i*pr[j]]=0,phi[i*pr[j]]=phi[i]*pr[j];break;}
  32. }
  33. }
  34. rep(i,1,bnd)phi[i]+=phi[i-1],mu[i]+=mu[i-1];
  35. }
  36. //ll sq,vmu[n12sz*2],vphi[n12sz*2];
  37. //ll tr(ll v){return v<}
  38. unordered_map<uint,ll> ansmu,ansphi;
  39. ll getphi(uint n){
  40. if(n<=bnd)return phi[n];
  41. ll &tmp=ansphi[n];
  42. if(tmp)return tmp;
  43. ull res=(ull)n*(n+1)/2;
  44. for(uint l=2,r;l<=n;l=r+1){//using unsigned int instead of ll
  45. r=n/(n/l);
  46. res-=(ll)(r-l+1)*getphi(n/l);
  47. }
  48. return tmp=res;
  49. }
  50. ll getmu(uint n){
  51. if(n<=bnd)return mu[n];
  52. ll &tmp=ansmu[n];
  53. if(tmp)return tmp;
  54. tmp=1;
  55. for(uint l=2,r;l<=n;l=r+1){
  56. r=n/(n/l);
  57. tmp-=(r-l+1)*getmu(n/l);
  58. }
  59. return tmp;
  60. }
  61. int main(){
  62. // freopen("a.in","r",stdin);
  63. ios::sync_with_stdio(0),cin.tie(0);
  64. init();
  65. cin>>t;
  66. rep(cs,1,t){
  67. cin>>n;
  68. cout<<getphi(n)<<' '<<getmu(n)<<'\n';
  69. }
  70. return 0;
  71. }

unordered_map的地方也可以换为

  1. struct tmap{
  2. ll a[sqsz],b[sqsz];
  3. void cl(){memset(b,0,sizeof(b));}
  4. ll& operator[](int p){
  5. if(p<5e4)return a[p];
  6. else return b[n/p];
  7. }
  8. }ansmu,ansphi;

但是并没有变快... 可能是unordered_map常数小吧...

[模板] 杜教筛 && bzoj3944-Sum的更多相关文章

  1. 杜教筛 && bzoj3944 Sum

    Description Input 一共T+1行 第1行为数据组数T(T<=10) 第2~T+1行每行一个非负整数N,代表一组询问 Output 一共T行,每行两个用空格分隔的数ans1,ans ...

  2. LG4213 【模板】杜教筛(Sum)和 BZOJ4916 神犇和蒟蒻

    P4213 [模板]杜教筛(Sum) 题目描述 给定一个正整数$N(N\le2^{31}-1)$ 求 $$ans_1=\sum_{i=1}^n\varphi(i)$$ $$ans_2=\sum_{i= ...

  3. Luogu 4213 【模板】杜教筛(Sum)

    当作杜教筛的笔记吧. 杜教筛 要求一个积性函数$f(i)$的前缀和,现在这个东西并不是很好算,那么我们考虑让它卷上另外一个积性函数$g(i)$,使$(f * g)$的前缀和变得方便计算,然后再反推出这 ...

  4. luoguP4213 【模板】杜教筛(Sum)杜教筛

    链接 luogu 思路 为了做hdu来学杜教筛. 杜教筛模板题. 卡常数,我加了register居然跑到不到800ms. 太深了. 代码 // luogu-judger-enable-o2 #incl ...

  5. [洛谷P4213]【模板】杜教筛(Sum)

    题目大意:给你$n$,求:$$\sum\limits_{i=1}^n\varphi(i),\sum\limits_{i=1}^n\mu(i)$$最多$10$组数据,$n\leqslant2^{31}- ...

  6. P4213 【模板】杜教筛(Sum)

    \(\color{#0066ff}{题 目 描 述}\) 给定一个正整数\(N(N\le2^{31}-1)\) 求 \(\begin{aligned} ans_1=\sum_{i=1}^n\varph ...

  7. 【模板】杜教筛(Sum)

    传送门 Description 给定一个正整数\(N(N\le2^{31}-1)\) 求 \[ans1=\sum_{i=1}^n \varphi(i)\] \[ans_2=\sum_{i=1}^n \ ...

  8. P4213【模板】杜教筛(Sum)

    思路:杜教筛 提交:\(2\)次 错因:\(\varphi(i)\)的前缀和用\(int\)存的 题解: 对于一类筛积性函数前缀和的问题,杜教筛可以以低于线性的时间复杂度来解决问题. 先要构造\(h= ...

  9. luoguP4213 [模板]杜教筛

    https://www.luogu.org/problemnew/show/P4213 同 bzoj3944 考虑用杜教筛求出莫比乌斯函数前缀和,第二问随便过,第一问用莫比乌斯反演来做,中间的整除分块 ...

随机推荐

  1. 坑:微信小程序wx.request和wx.uploadFile中传参数的区别

    微信小程序中通过组件<form>提交表单的时候,在js中通过e.detail.value得到所提交表单的json格式数据.一般提交表单我们都是通过wx.request请求,提交表单数据,通 ...

  2. 基础环境系列:MySQL8.0.12

    机型与版本:windows10(64-bits) Mysql环境配置:mysql8.0.12 一.MySQL安装 Mysql的安装有两种方法,一种是通过.msi一种是通过压缩包.穷呢,大家就老实下社区 ...

  3. 关于测试:JUnit4课程

    JUnit4课程 JUnit4快速入门 测试实践 1.导入jar(右键Build Path --> Add Libraries --> Junit --> Junit4) 2.新建测 ...

  4. PSP总结报告

    此作业的要求参见[https://edu.cnblogs.com/campus/nenu/2018fall/homework/2556] 回顾0 alpha阶段前 团队名称:可以低头,但没必要 团队项 ...

  5. 前后端分离djangorestframework——ContentType组件表

    ContentType ContentType其实django自带的,但是平时的话很少会用到,所以还是放在Djangorestframework这个部分 作用: 在实际的开发中,由于数据库量级大,所以 ...

  6. c/c++ 拷贝控制 右值与const引用

    拷贝控制 右值与const引用 背景:当一个函数的返回值是自定义类型时,调用侧用什么类型接收?? 1,如果自定义类型的拷贝构造函数的参数用const修饰了:可以用下面的方式接收. Test t2 = ...

  7. 【PAT】B1018 锤子剪刀布

    抄的柳婼小姐姐的,感觉三个数求最大那里用的真棒 #include <stdio.h> int main() { int N; scanf("%d", &N); ...

  8. Maven构建项目出现No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?

    No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK? 你应该 ...

  9. Extjs 解决grid分页bug问题

    //从后端获取数据加载到grid中var mainStore = new HeJsonStore({ url:'xxx', autoLoad:true, pageSize:20 }) //此方法最好放 ...

  10. CSS--字体|垂直居中|background

    一,字体的设置 二,垂直居中 2.1,单行文本垂直居中 2.2,多行文本垂直居中 2.3,绝对定位元素垂直居中 三.颜色的表示法 四.background ---------------------- ...