入门杜教筛啦。

http://blog.csdn.net/skywalkert/article/details/50500009(好文!)

可以在$O(N^{\frac{2}{3}})或O(N^{\frac{3}{4}})$的复杂度内解决求某些数论函数f(n)(或f的前缀和S(n)$)的值。

先来看看原理是什么。(接下来推导如何求数论函数f(n)的前缀和S(n))


现在有两个数论函数$f( )和g( )$

(同时定义f的前缀和函数$S(n)=\sum_{i=1}^{n}f(i)$)

有狄利克雷乘积可知:

$$f*g(n)=\sum_{i|n}f(\frac{n}{i})g(i)\quad(=\sum_{i|n}f(i)g(\frac{n}{i}))$$

那么,则有如下结论:

$$\sum_{n=1}^{N}f*g(n)=\sum_{i=1}^{N}g(i)S(\lfloor \frac{N}{i} \rfloor)$$

证明如下:

$$\begin{align*}
\sum_{n=1}^{N}f*g(n)&=\sum_{n=1}^{N}\sum_{i|n}f(\frac{n}{i})g(i)\\
&=\sum_{i=1}^{N}g(i)\sum_{i=1}^{\lfloor \frac{N}{i} \rfloor}f(i)\\
&=\sum_{i=1}^{N}g(i)S(\lfloor \frac{N}{i} \rfloor)
\end{align*}$$

然后把右边和式里的$g(1)S(N)$那一项提出来得到:

$$g(1)S(N)=\sum_{n=1}^{N}f*g(n)-\sum_{i=2}^{N}g(i)S(\lfloor \frac{N}{i} \rfloor)$$

通常令数论函数$g(n)=I(n)=1$(恒等函数$l(n)=1$,完全积性)

到目前为止,上式就是我们进行杜教筛的基础了。

因为左边的S(N)就是答案,而右边同时又可以用分块的方式计算。

不少刚刚入门的同学会有一个疑问,等式右边的后半部分确实可以分块计算,但是前半部分怎么办呢?

其实,一般前面的$\sum_{n=1}^{N}f*g(n)$都是可以O(1)计算出来的。

下面来看两个例子:


(一)、求莫比乌斯函数$\mu(n)$的前缀和函数$S(n),n \leq 10^9$

首先添加一个辅助函数g(n)=l(n)=1,

然后重复上面的过程,可以得到

$$g(1)S(N)=\sum_{n=1}^{N}\mu*g(n)-\sum_{i=2}^{N}g(i)S(\lfloor \frac{N}{i} \rfloor)$$

$$S(N)=\sum_{n=1}^{N}\mu*g(n)-\sum_{i=2}^{N}S(\lfloor \frac{N}{i} \rfloor)$$

现在来看看$\sum_{n=1}^{N}\mu*g(n)$怎么求:

$$\begin{aligned}
\sum_{n=1}^{N}\mu*g(n)&=\sum_{n=1}^{N}\sum_{i|n}\mu(i)g(\frac{n}{i})\\
&=\sum_{n=1}^{N}\sum_{i|n}\mu(i)\\
&=\sum_{n=1}^{N}[n==1]\\
&=1
\end{aligned}$$

上面的化简用到了刚刚学莫比乌斯函数时的一个结论:

$$\sum_{i|n}\mu(i)=[n==1]$$

到此,我们得到:

$$S(N)=1-\sum_{i=2}^{N}S(\lfloor \frac{N}{i} \rfloor)$$

实现方式是分块计算+记忆化递归处理(用map或者hash表记忆化)


(二). 求欧拉函数$\phi(n)$的前缀和函数$S(n),n \leq 10^9$

同样地,添加一个辅助函数g(n)=l(n)=1,

然后重复上面的过程,可以得到

$$g(1)S(N)=\sum_{n=1}^{N}\phi*g(n)-\sum_{i=2}^{N}g(i)S(\lfloor \frac{N}{i} \rfloor)$$

$$S(N)=\sum_{n=1}^{N}\phi*g(n)-\sum_{i=2}^{N}S(\lfloor \frac{N}{i} \rfloor)$$

$\sum_{n=1}^{N}\phi*g(n)$又怎样求呢:

$$\begin{aligned}
\sum_{n=1}^{N}\phi*g(n)&=\sum_{n=1}^{N}\sum_{i|n}\phi(i)g(\frac{n}{i})\\
&=\sum_{n=1}^{N}\sum_{i|n}\phi(i)\\
&=\sum_{n=1}^{N}n\\
&=\frac{(1+n)n}{2}
\end{aligned}$$

上面的化简用到了这样一个结论:

$$\sum_{i|n}\phi(i)=n$$

所以我们得到:

$$S(N)=\frac{(1+n)n}{2}-\sum_{i=2}^{N}S(\lfloor \frac{N}{i} \rfloor)$$

这个同样是实现方式是分块计算+记忆化递归处理(用map或者hash表记忆化)


下面是代码具体实现:

关于时间复杂度的分析不太会。记了一下结论。

通常不做任何处理,就直接杜教筛的话(分块计算+记忆化递归处理),复杂度是$O(N^{\frac{3}{4}})$

但是如果预处理出前$N^{\frac{2}{3}}$个前缀和,那么总的复杂度就可以降到$O(N^{\frac{2}{3}})$

BZOJ 3944: Sum,杜教筛入门题。

多个询问,给出N,求$\sum_{n=1}^{N}\mu(n)$和$\sum_{n=1}^{N}\phi(n)$

也就是求上面的两个例子。

这里直接给出代码,用的是预处理前$N^{\frac{2}{3}}$个前缀和+hash表进行记忆化。

复杂度$O(N^{\frac{2}{3}})$

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define DJM 1664510
//#define DJM 10
#define ll long long
using namespace std;
ll phi[DJM+50],mu[DJM+50];
struct Pii{
int x; ll a,b;
Pii(int _x=0,ll _a=0,ll _b=0):x(_x),a(_a),b(_b){}
}nl;
struct Hash_Table{//
#define hmod 1425367
int nxt[hmod],head[hmod],hnt;
Pii info[hmod];
Hash_Table(){hnt=2;}
void Push(Pii rtm){
static int u; u=rtm.x%hmod;
info[hnt]=rtm; nxt[hnt]=head[u]; head[u]=hnt++;
}
Pii Find(int x){
static int u; u=x%hmod;
for(int i=head[u];i;i=nxt[i]) if(info[i].x==x) return info[i];
return nl;
}
}H;
void Sieve(){
static bool np[DJM+50];
static int prime[DJM+50],pnt;
phi[1]=mu[1]=1;
for(int i=2;i<=DJM;i++){
if(!np[i]) prime[++pnt]=i,mu[i]=-1,phi[i]=i-1;
for(int j=1;j<=pnt&&i<=DJM/prime[j];j++){
np[i*prime[j]]=1;
if(i%prime[j]){mu[i*prime[j]]=-mu[i]; phi[i*prime[j]]=phi[i]*phi[prime[j]];}
else{phi[i*prime[j]]=phi[i]*prime[j]; break;}
}
}
for(int i=2;i<=DJM;i++) mu[i]+=mu[i-1],phi[i]+=phi[i-1];
}
Pii DJ_Sieve(int x){
if(x<=DJM) return Pii(x,mu[x],phi[x]);
if(H.Find(x).x) return H.Find(x);
Pii tmp,now=Pii(x,1,(1ll+x)*x/2);
for(ll i=2,last;i<=x;i=last+1){
last=x/(x/i); tmp=DJ_Sieve(x/i);
now.a-=tmp.a*(last-i+1); now.b-=tmp.b*(last-i+1);
}
H.Push(now); return now;
}
int main(){
Sieve();
int Case,n; Pii ans;
scanf("%d",&Case);
for(int i=1;i<=Case;i++){
scanf("%d",&n);
if(n==0) {printf("0 0\n"); continue;}
ans=DJ_Sieve(n);
printf("%lld %lld\n",ans.b,ans.a);
}
return 0;
}

  

●杜教筛入门(BZOJ 3944 Sum)的更多相关文章

  1. bzoj 3944 Sum —— 杜教筛

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

  2. luogu 3768 简单的数学题 (莫比乌斯反演+杜教筛)

    题目大意:略 洛谷传送门 杜教筛入门题? 以下都是常规套路的变形,不再过多解释 $\sum\limits_{i=1}^{N}\sum\limits_{j=1}^{N}ijgcd(i,j)$ $\sum ...

  3. bzoj 3944: Sum(杜教筛)

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

  4. bzoj 3944: Sum【莫比乌斯函数+欧拉函数+杜教筛】

    一道杜教筛的板子题. 两个都是积性函数,所以做法是一样的.以mu为例,设\( f(n)=\sum_{d|n}\mu(d) g(n)=\sum_{i=1}^{n}f(i) s(n)=\sum_{i=1} ...

  5. 3944: Sum[杜教筛]

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

  6. bzoj 3944 杜教筛

    题目中要求phi和miu的前缀和,利用杜教筛可以推出公式.我们令为 那么有公式 类比欧拉函数,我们可以推出莫比乌斯函数的和公式为  (公式证明懒得写了,主要核心是利用Dirichlet卷积的性质 ph ...

  7. BZOJ 4805: 欧拉函数求和 杜教筛

    https://www.lydsy.com/JudgeOnline/problem.php?id=4805 给出一个数字N,求sigma(phi(i)),1<=i<=N https://b ...

  8. BZOJ3944: Sum(杜教筛模板)

    BZOJ3944: Sum(杜教筛模板) 题面描述 传送门 题目分析 求\(\sum_{i=1}^{n}\mu(i)\)和\(\sum_{i=1}^{n}\varphi(i)\) 数据范围线性不可做. ...

  9. [BZOJ3944]Sum(杜教筛)

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

随机推荐

  1. Beta 凡事预则立

    写在Beta冲刺前 关于组长是否重选的议题和结论 总体结论 组长无需更换 队内无人替代 理由 当前组长能够较好的号召和组织团队成员进行工作 当前组长能够对项目有合理的规划 当前组长被大家一致认可可以继 ...

  2. python第三方库requests详解

    Requests 是用Python语言编写,基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库.它比 urllib 更加方便,可以节约我们大量的工作,完全满足 HTT ...

  3. Count on a tree

    bzoj  2588: Spoj 10628. Count on a tree http://www.lydsy.com/JudgeOnline/problem.php?id=2588 Descrip ...

  4. Python内置函数(19)——oct

    英文文档: oct(x) Convert an integer number to an octal string. The result is a valid Python expression. ...

  5. python subprocess模块使用总结

    一.subprocess以及常用的封装函数运行python的时候,我们都是在创建并运行一个进程.像Linux进程那样,一个进程可以fork一个子进程,并让这个子进程exec另外一个程序.在Python ...

  6. Spring Framework 的 Assert断言

    知识共享才能传播,博采众家之长,才能推陈出新!-- 参考 https://www.cnblogs.com/hwaggLee/p/4778101.html 一.什么是 Assert(断言)? Web 应 ...

  7. hadoop2.6.0实践:引入开发依赖的jar包

    hadoop-2.5.0\share\hadoop\common  所有jar,hadoop-2.5.0\share\hadoop\common\lib  所有jar,hadoop-2.5.0\sha ...

  8. redis入门(06)各种类型的操作命令

    Redis 字符串命令下表列出了常用的 redis 字符串命令:序号 命令及描述1 SET key value 设置指定 key 的值2 GET key 获取指定 key 的值.3 GETRANGE ...

  9. 模板引擎ejs详解

    singsingasong.js: const ejs=require('ejs'); ejs.renderFile('./views/singsingasong.ejs', {'name':'sin ...

  10. python3全栈开发-面向对象、面向过程

    一. 什么是面向对象的程序设计及为什么要有它 1.面向过程 面向过程的程序设计:核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么......面向过程的设计就好比精心设计好一条流水线,是一种 ...