BZOJ3944: Sum(杜教筛模板)


题面描述

传送门

题目分析

求\(\sum_{i=1}^{n}\mu(i)\)和\(\sum_{i=1}^{n}\varphi(i)\)

数据范围线性不可做。

需要使用杜教筛。

杜教筛可以在非线性时间里求出一个积性函数的前缀和。

借这里先写一些杜教筛内容。。。或许以后会补总结(雾

最开始扔积性函数:

  1. \(\mu(n)\),莫比乌斯函数
  2. \(\phi(n)\),欧拉函数。
  3. \(d(n)\),约数个数。
  4. \(\sigma(n)\),约数和函数。
  5. \(\epsilon(n)\),元函数,其值为\(\epsilon(n)=[n=1]\)。
  6. \(id(n)\),单位函数,\(id(n)=n\)。
  7. \(I(n)\),恒等函数,\(I(n)=1\)。

先放狄利克雷卷积的式子:

假设我们现在有两个数论函数\(f,g\),则这两个函数的卷积是\((f*g)(n)=\sum_{d\mid n}f(d)·g(\frac{n}{d})\)后面的括号表示范围,一般不写的时候可以默认其为\(n\)。

可以推出狄利克雷卷积满足以下运算律

  1. 交换律:\((f∗g=g∗f)\);
  2. 结合律:\(((f∗g)∗h=f∗(g∗h))\);
  3. 分配律:\(((f+g)∗h=f∗h+g∗h)\);

可以类比乘法运算律记忆。

那么我们可以开始搞杜教筛了。

现在我们要求一个积性函数\(f\)的前缀和,也就是\(\sum_{i=1}^{n}f(i)\)。

我们尝试构造两个积性函数使\(h=f*g\)

那么我们求一下\(\sum_{i=1}^{n}h(i)\)。

先记\(Sum(n)\)为\(\sum_{i=1}^{n}f(i)\)

则:

\[\sum_{i=1}^{n}h(i)=\sum_{i=1}^{n}\sum_{d\mid i}g(d)f(\frac{i}{d})
\]

然后明显可以反过来枚举。

\[→\sum_{d=1}^{n}g(d)\sum_{d\mid i}f(\frac{i}{d})
\]

改成枚举\(\frac{i}{d}\)

\[→\sum_{d=1}^{n}g(d)\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}f(i)=\sum_{d=1}^{n}g(d)S(\lfloor\frac{n}{d}\rfloor)
\]

然后把式子的第一项提出来,整个代回去。

\[\sum_{i=1}^{n}h(i)=g(1)·S(n)+\sum_{d=2}^{n}g(d)·S(\lfloor\frac{n}{d}\rfloor)
\]

移项

\[g(1)·S(n)=\sum_{i=1}^{n}h(i)-\sum_{d=2}^{n}g(d)·S(\lfloor\frac{n}{d}\rfloor)
\]

这样\(g(1)\)明显为\(1\),所以这个式子就很明显了,只要\(h(i)\)的前缀和好求那么这个式子就可以在非线性时间里求出来了。

因为\(h=f*g\)我们换个形式表示上面的式子。

\[→g(1)·S(n)=\sum_{i=1}^{n}(f*g)(i)-\sum_{d=2}^{n}g(d)·S(\lfloor\frac{n}{d}\rfloor)
\]

所以只要找到一个合适的\(g\)就行了。

看个例子,我们这个题要求啥来着,\(\sum_{i=1}^{n}\mu(i)\)和\(\sum_{i=1}^{n}\varphi(i)\)

先看第一个。

就不推了,根据上面那个把\(f\)换成\(\mu\)直接代到最后面。

那么应该怎么给\(g\)取值呢,我们可以简明扼要的先看一下那一项变成什么了。

\[→\sum_{i=1}^{n}(\mu*g)(i)
\]

有一个好消息,我们知道\(\mu*I=\epsilon\)。那么可以把上面的式子看成

\[\sum_{i=1}^{n}(\mu*I)(i)=\sum_{i=1}^{n}\epsilon(i)
\]

元函数的前缀和就非常好求,就是\(1\),所以我们求的答案

\[S(n)=1-\sum_{d=2}^{n}g(d)·S(\lfloor\frac{n}{d}\rfloor)
\]

再看第二个,我们还是相同的直接把\(\varphi\)代到最后面去。

则我们有式子

\[\sum_{i=1}^{n}(\varphi*g)(i)
\]

思考一下,我们记得欧拉函数有个有趣的性质\(\sum_{d|n}\varphi(d)=n\)

我们把它用卷积的形式表达,就是\(\varphi*I=id\)

带入刚才的式子里面。

\[\sum_{i=1}^{n}(\varphi*g)(i)=\sum_{i=1}^{n}id(i)
\]

明显的小高斯5岁就会的那个数列求和。。。

这个东西是\(n·(n+1)/2\)应该都知道。。。

然后代码实现的时候,可以先筛出根号范围内的答案,然后递归处理记忆化搜索。

由于需要储存下标非常大的值,所以需要使用哈希或者偷懒使用unordered_map,不要用map,会多一个log。

下面代码实测BZOJ可过,注意少开long long

是代码呢

  1. #include <bits/stdc++.h>
  2. #include <tr1/unordered_map>
  3. using namespace std;
  4. const int MAXN=4e6+7;
  5. const int M=4e6;
  6. #define ll long long
  7. bool vis[MAXN];
  8. int mu[MAXN],sum1[MAXN];
  9. ll phi[MAXN],sum2[MAXN];
  10. int cnt,prime[MAXN];
  11. tr1::unordered_map<ll,ll> w1;
  12. tr1::unordered_map<int,short> w;
  13. inline void get(int N)
  14. {
  15. phi[1]=mu[1]=1;
  16. for(int i=2;i<=N;i++){
  17. if(!vis[i]){
  18. prime[++prime[0]]=i;
  19. mu[i]=-1;
  20. phi[i]=i-1;
  21. }
  22. for(int j=1;j<=prime[0];j++){
  23. if(i*prime[j]>N) break;
  24. vis[i*prime[j]]=1;
  25. if(i%prime[j]==0){
  26. phi[i*prime[j]]=phi[i]*prime[j];
  27. break;
  28. } else mu[i*prime[j]]=-mu[i],phi[i*prime[j]]=phi[i]*(prime[j]-1);
  29. }
  30. }
  31. for(int i=1;i<=N;i++) sum1[i]=sum1[i-1]+mu[i],sum2[i]=sum2[i-1]+phi[i];
  32. }
  33. int djsmu(int x)
  34. {
  35. if(x<=M) return sum1[x];
  36. if(w[x]) return w[x];
  37. int ans=1;
  38. for(int l=2,r;l<=x;l=r+1){
  39. if(r==2147483647) break;
  40. r=x/(x/l);
  41. ans-=(r-l+1)*djsmu(x/l);
  42. }
  43. return w[x]=ans;
  44. }
  45. ll djsphi(int x)
  46. {
  47. if(x<=M) return sum2[x];
  48. if(w1[x]) return w1[x];
  49. ll ans=1ll*x*(1ll*x+1)/2;
  50. for(int l=2,r;l<=x&&l>=0;l=r+1){
  51. if(r==2147483647) break;
  52. r=x/(x/l);
  53. ans-=1ll*(r-l+1)*djsphi(x/l);
  54. }
  55. return w1[x]=ans;
  56. }
  57. inline int read()
  58. {
  59. int x=0,c=1;
  60. char ch=' ';
  61. while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
  62. while(ch=='-')c*=-1,ch=getchar();
  63. while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
  64. return x*c;
  65. }
  66. int main()
  67. {
  68. int T=read();
  69. get(M);
  70. while(T--){
  71. int n;
  72. n=read();
  73. printf("%lld %d\n", djsphi(n),djsmu(n));
  74. }
  75. }

BZOJ3944: Sum(杜教筛模板)的更多相关文章

  1. [bzoj3944] sum [杜教筛模板]

    题面: 传送门 就是让你求$ \varphi\left(i\right) $以及$ \mu\left(i\right) $的前缀和 思路: 就是杜教筛的模板 我们把套路公式拿出来: $ g\left( ...

  2. [BZOJ3944]Sum(杜教筛)

    3944: Sum Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 6201  Solved: 1606[Submit][Status][Discuss ...

  3. 【Bzoj3944】杜教筛模板(狄利克雷卷积搞杜教筛)

    题目链接 哇杜教筛超炫的 有没有见过$O(n^\frac{2}{3})$求欧拉函数前缀和的算法?没有吧?蛤蛤蛤 首先我们来看狄利克雷卷积是什么 首先我们把定义域是整数,陪域是复数的函数叫做数论函数. ...

  4. bzoj3944: Sum 杜教筛板子题

    板子题(卡常) 也可能是用map太慢了 /************************************************************** Problem: 3944 Us ...

  5. 3944: Sum[杜教筛]

    3944: Sum Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3471  Solved: 946[Submit][Status][Discuss] ...

  6. 洛谷P4213 Sum(杜教筛)

    题目描述 给定一个正整数N(N\le2^{31}-1)N(N≤231−1) 求ans_1=\sum_{i=1}^n\phi(i),ans_2=\sum_{i=1}^n \mu(i)ans1​=∑i=1 ...

  7. bzoj 3944 Sum —— 杜教筛

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3944 杜教筛入门题! 看博客:https://www.cnblogs.com/zjp-sha ...

  8. BZOJ 3944: Sum [杜教筛]

    3944: Sum 贴模板 总结见学习笔记(现在还没写23333) #include <iostream> #include <cstdio> #include <cst ...

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

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

随机推荐

  1. BOM history对象

    history对象的三个可用方法和一个属性 back();后退 forward();前进 go(n);跳到第几个页面,负数为后退,正数为前进 length属性,获取缓存的页面的数量 安全性考虑,his ...

  2. 运行npm install出现警告

    如下: 解决: fsevent是mac osx系统的,你是在win或者Linux下使用了 所以会有警告,忽略即可

  3. Linux系统下Redis缓存安装配置

    Redis是一个高性能的key-value数据库,现时越来越多企业与应用使用Redis作为缓存服务器.楼主是一枚JAVA后端程序员,也算是半个运维工程师了.在Linux服务器上搭建Redis,怎么可以 ...

  4. SQL的子查询操作

    对于表中的每一个记录,我们有时候需要提取特殊的或者你需要的记录,要提前做一个表的筛选,之后再对你选出的记录做一个修改,此时你必须使用SQL的子查询操作.如:修改id=5的记录的strContent字段 ...

  5. installEventFilter可以安装到任何QObject的子类,并不仅仅是UI组件。事件过滤器和安装过滤器的组件必须在同一线程,在它们分属在不同线程时,事件过滤器也是不起作用的

    Qt的事件知识点: ①事件对象创建完毕后,Qt 将这个事件对象传递给 QObject 的 event() 函数.event() 函数并不直接处理事件,而是将这些事件对象按照它们不同的类型,分发给不同的 ...

  6. Strategic Game--hdu1054(最小覆盖点)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1054 求最小覆盖点,也就是求最大匹配,要用邻接表写,不然会TLE:当然也可以用HK算法: #inclu ...

  7. linux下的进程,子进程,线程

    1.相同点:(a)二者都具有ID,一组寄存器,状态,优先级以及所要遵循的调度策略.(b) 每个进程都有一个进程控制块,线程也拥有一个线程控制块.(c) 线程和子进程共享父进程中的资源:线程和子进程独立 ...

  8. How Instagram Feeds Work: Celery and RabbitMQ(转)

    原文:http://blogs.vmware.com/vfabric/2013/04/how-instagram-feeds-work-celery-and-rabbitmq.html Instagr ...

  9. python获取当天日期进行格式转换

    # Python Library import time def getToday(format=3): """返回今天的日期字串""" # ...

  10. Spark SQL与Hive on Spark的比较

    简要介绍了SparkSQL与Hive on Spark的区别与联系 一.关于Spark 简介 在Hadoop的整个生态系统中,Spark和MapReduce在同一个层级,即主要解决分布式计算框架的问题 ...