杜教筛学习笔记

本来是想和 Min_25 一起写的,但是太长了(为了避免莫反那篇一样的惨案)所以就分开了w.

0 - 前置

莫比乌斯反演

详见 莫比乌斯反演学习笔记 ,这里摘录一些式子。

Dirichlet卷积:

\[(f*g)(x)=\sum_{d|x}f(d)g(\frac{x}{d}) \]

莫比乌斯反演:

\[f=g*1=>g=f*\mu\\ f(x)=\sum_{d|x}g(d)=>g(x)=\sum_{d|x}f(d)\times \mu(\frac{x}{d}). \]

欧拉函数

性质:\(\sum_{d|n} \varphi(d)=n\)

表示成 Dirichlet卷积 的形式:\(\varphi*I=id\) .

卷上 \(\mu\)

\[\varphi*I=id\\ =>\varphi*I*\mu=id*\mu\\ =>\varphi * \epsilon=id*\mu \]

所以有

\[\varphi(n)=\sum_{d|n}\mu(d)\cdot\frac{n}{d} \]

\[\frac{\varphi(n)}{n}=\sum_{d|n}\frac{\mu(d)}{d} \]

1 - 杜教筛

Method

用途:以低于线性的复杂度计算积性函数前缀和 ,即计算:\(\sum_{i=1}^n f(i)\) .

推导:

构造两个积性函数 \(h,g\) ,使得 \(h=f*g\) .

\(S(n)=\sum_{i=1}^n f(i)\) ,那么有

\[\begin{aligned} \sum_{i=1}^nh(i) &=\sum_{i=1}^n\sum_{d|i}g(d)\cdot f(\frac{i}{d})\\\\ &=\sum_{d=1}^ng(d)\cdot \sum_{i=1}^{\lfloor n/d\rfloor} f(i)\\\\ &=\sum_{d=1}^ng(d)\cdot S(\lfloor \frac{n}{d}\rfloor )\\\\ &=g(1)\cdot S(n)+\sum_{d=2}^{n}g(d)\cdot S(\lfloor\frac{n}{d}\rfloor)\\\\ g(1)S(n)&=\sum_{i=1}^nh(i)-\sum_{d=2}^ng(d)\cdot S(\lfloor \frac{n}{d}\rfloor ) \end{aligned} \]

所以关键就在于找一个容易得到的 \(h\) .求得之后对后面整除分块就好了,复杂度 \(\mathcal{O}(n^{\frac 23})\) .

关于复杂度 (@George1123)

直接递归求是 \(\Theta(n^{\frac{3}{4}})\)

\[\begin{split} T(n)=&\sqrt n+\sum\limits_{i=2}^{\sqrt n}\left(T(i)\cdot T(\lfloor\frac{n}{i}\rfloor)\right)\\ \ge&\sqrt n+\sum\limits_{i=2}^{\sqrt n}\left(\sqrt i\cdot \sqrt{\lfloor\frac{n}{i}\rfloor)}\right)\\ \ge&\sqrt n+\sum\limits_{i=2}^{\sqrt n}2\sqrt{\sqrt n}\\ =&n^{\frac{3}{4}}\\ \end{split} \]

线性筛求出前 \(n^{\frac23}\) 个,然后再杜教筛,是 \(\Theta(n^{\frac{2}{3}})\) .

\[\begin{split} T(n)=&m+\sum\limits_{i=2}^{\lfloor\frac nm\rfloor}\sqrt{\lfloor\frac ni\rfloor}\\ =&m+\frac{n}{\sqrt m}\\ \ge&2n^{\frac{2}{3}}(=: \operatorname{while} m=n^{\frac{2}{3}})\\ \end{split} \]

Example

莫比乌斯函数

\[S(n)=\sum_{i=1}^n\mu(i). \]

由于 \(\mu*I=\epsilon\) ,所以 令 \(I=>g,\epsilon=>h\) ,根据上面的式子

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

\[\begin{aligned} 1\times S(n)&=\sum_{i=1}^n\epsilon(i)-\sum_{d=2}^nS(\lfloor \frac{n}{d}\rfloor )\\\\ S(n) &= 1-\sum_{d=2}^nS(\lfloor \frac nd\rfloor) \end{aligned} \]

欧拉函数

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

由于 \(\varphi *I=ID\) ,所以

\[\begin{aligned} S(n) &=\sum_{i=1}^n i-\sum_{d=2}^n S(\lfloor \frac{n}{d}\rfloor)\\\\ &=\frac{n(n+1)}{2}-\sum_{d=2}^nS(\lfloor \frac{n}{d}\rfloor) \end{aligned} \]

?函数

\[S(n)=\sum_{i=1}^ni\cdot \varphi(i) \]

考虑 Dirichlet卷积的形式:

\[\sum_{d|n}(d\cdot \varphi(d))\cdot g(\frac{n}{d}) \]

\(ID=>g\) ,有

\[\sum_{d|n}(d\cdot \varphi(d))\cdot \frac{n}{d}=\sum_{d|n}n\cdot \varphi(d)=n\sum_{d|n}\varphi(d)=n^2 \]

所以有

\[S(n)=\sum_{i=1}^ni^2-\sum_{d=2}^nd\cdot S(\lfloor \frac{n}{d}\rfloor) \]

??函数

\[\sum_{i=1}^n\mu(i)i^2 \]

\(g(i)=i^2\) ,有

\[g*f(n)=\sum_{d|n}\mu(d)d^2\cdot\Big(\frac{n}{d}\Big)^2=\sum_{d|n}\mu(d)=[n=1] \]

所以

\[S(n)=\sum_{i=1}^nh(i)-\sum_{d=2}^nd^2\cdot S(\lfloor \frac{n}{d}\rfloor )=1-\sum_{d=2^n}d^2\cdot S(\lfloor \frac{n}{d}\rfloor) \]

Code

大常数选手打的 模板

代码见模板库

下面是例题。

例题:SPOJ GCDEX2

\[\begin{aligned} \sum_{i=1}^n\sum_{j=i+1}^n \gcd(i,j)&=\sum_{i=1}^n\sum_{j=1}^{i-1}\gcd(i,j)\\\\ &=\sum_{d=1}^nd\sum_{i=1}^{\lfloor n/d\rfloor}\sum_{j=1}^{i-1}[\gcd(i,j)=1]\\\\ &=\sum_{d=1}^nd\sum_{i=1}^{\lfloor n/d\rfloor}\varphi(i) \end{aligned} \]

杜教筛+整除分块板题。(总感觉cf用心险恶 /xia

稍微写下是怎么从列表末尾松到头的:

  • 众所周知杜教筛卡常可以尽可能大量初始化
  • 线性筛的时候可以不用 vis ,直接以 \(\varphi\) 判断是否做过
  • 所有本来开 long long 的都改成 unsigned long long ,避免大量的转换

第一名实在松不过 /shake

Code

例题:毒瘤的数学题

\[\left(\sum\limits_{i=1}^n\sum\limits_{j=1}^nij\gcd(i,j)\right)\bmod p \]

\(1\le n\le 10^{10},5\times10^{8}\le p\le 1.1\times 10^{9}\) .

Solution

\[\begin{aligned} \sum_{i=1}^n\sum_{j=1}^nij\gcd(i,j) &=\sum_{d=1}^n d^3\sum_{i=1}^{\lfloor n/d\rfloor}\sum_{j=1}^{\lfloor n/d\rfloor} ij[\gcd(i,j)=1]\\\\ &=\sum_{d=1}^nd^3\sum_{i=1}^{\lfloor n/d\rfloor}\sum_{j=1}^{\lfloor n/d\rfloor}ij\sum_{k|d}\mu(k)\\\\ 令S(n)=\frac{n*(n+1)}2,&=\sum_{d=1}^nd^3\sum_{k|d}\mu(k)k^2S(\lfloor \frac{n}{dk}\rfloor)^2\\\\ &=\sum_{d=1}^nd^3\sum_{k=1}^{\lfloor n/d\rfloor}\mu(k)k^2S(\lfloor \frac{n}{dk}\rfloor)^2 \end{aligned} \]

\(T=dk\) 进行代换,得到:

\[\begin{aligned} \sum_{d=1}^nd^3\sum_{k=1}^{\lfloor n/d\rfloor}\mu(k)k^2S(\lfloor \frac{n}{dk}\rfloor)^2 &=\sum_{d=1}^nd^3\sum_{k=1}^{\lfloor n/d\rfloor}\mu(k)k^2S(\lfloor \frac{n}{T}\rfloor)^2\\\\ &=\sum_{T=1}^nS(\lfloor \frac nT\rfloor)^2\sum_{d|T}d^3\mu\Big(\frac{T}{d}\Big)\Big(\frac{T}{d}\Big)^2\\\\ &=\sum_{T=1}^nS(\lfloor \frac nT\rfloor)^2T^2\sum_{d|T}\mu\Big(\frac{T}{d}\Big)\cdot d\\\\ \end{aligned} \]

根据莫反中的前置知识,有

\[\varphi(x)=(\mu*ID)(x)=\sum\limits_{d|x}d\cdot\mu(\frac xd)\\\\ \]

所以:

\[=\sum_{T=1}^nS(\lfloor \frac{n}{T}\rfloor )^2T^2\varphi(T)\\\\ \]

然后就可以愉快地杜教筛了。把模板掏下来以便观察:

\[g(1)S(n)=\sum_{i=1}^nh(i)-\sum_{d=2}^ng(d)\cdot S(\lfloor \frac{n}{d}\rfloor )(杜教筛)\\\\ (f*g)(x)=\sum_{d|x}f(d)g(\frac{x}{d})(Dirichlet卷积)\\\\ \varphi*1=ID(和\varphi 有关的前置式子) \]

\(sum(n)=\sum_{i=1}^ni^2\varphi(i)\) ,显然我们需要把 \(sum(n)\) 中这个 \(i^2\) 消掉。看着卷积式子,考虑令 \(g(n)=n^2\) .

于是有:

\[(f*g)(n)=\sum_{d|n}d^2\varphi(d)\Big(\frac{n}{d}\Big)^2=n^2\sum_{d|n}\varphi(d) \]

然后再把最后一个式子给摁上去:

\[(f*g)(n)=n^3. \]

那么就有:

\[sum(n)=\sum_{i=1}^ni^3-\sum_{d=2}^nd^2sum(\lfloor \frac{n}{d}\rfloor)\\\\ \]

对于原式:

\[\sum_{T=1}^nS(\lfloor \frac{n}{T}\rfloor )^2T^2\varphi(T)\\\\ \]

就可以杜教筛解决了。

//Author: RingweEH
int power( int a,int b ) //快速幂
void Sieve()
{
	//筛 pri & phi
	for ( int i=1; i<=(N-10); i++ )
		sum[i]=(1ll*i*i%Mod*phi[i]%Mod+sum[i-1])%Mod;
}

int pow1( ll x )
{ x%=Mod; int res=x*(x+1)%Mod*inv2%Mod; return res; }
int pow2( ll x )
{ x%=Mod; int res=1ll*x*(x+1)%Mod*(2*x+1)%Mod*inv6%Mod; return res; }
int pow3( ll x )
{ int res=pow1(x); res=1ll*res*res%Mod; return res; }

unordered_map<ll,int> mp;
int Sieve_Mu( ll x )
{
	if ( x<=(N-10) ) return sum[x];
	if ( mp[x] ) return mp[x];
	int res=pow3(x);
	for ( ll l=2,r; l<=x; l=r+1 )
	{
		r=x/(x/l); res=(res-1ll*(pow2(r)-pow2(l-1))*Sieve_Mu(x/l)%Mod)%Mod;
	}
	mp[x]=(res+Mod)%Mod; return mp[x];
}

void init()
{
	Sieve(); inv2=power( 2ll,Mod-2 ); inv6=power( 6ll,Mod-2 );
}

int main()
{
	Mod=read(),n=read(); init();

	ll ans=0;
	for ( ll l=1,r; l<=n; l=r+1 )
	{
		r=n/(n/l); ans=(ans+1ll*(Sieve_Mu(r)-Sieve_Mu(l-1))*pow3(n/l)%Mod)%Mod;
	}

	printf( "%lld\n",(ans+Mod)%Mod );

	return 0;
}

例题:循环之美

求对于十进制下的 \(1\leq x\leq n,1\leq y\leq m\) ,有多少不相等的小数 \(\dfrac{x}{y}\)\(k\) 进制下是纯循环小数。

\(1\leq n,m\leq 1e9,k\leq 2000\) .

Solution

以下过程默认 \(\gcd(x,y)=1\) 。(这个很显然吧)

对于一个 \(k\) 进制下能成为纯循环小数的数,一定存在一个 \(t\) ,使得 \(k^t\cdot \dfrac{x}{y}\) 的小数部分等于 \(\dfrac xy\) ,即

\[k^t\cdot \dfrac{x}{y}-\Big\lfloor k^t\cdot \dfrac{x}{y}\Big\rfloor =\dfrac xy =>k^tx-y\cdot \Big\lfloor k^t\cdot \dfrac xy \Big\rfloor =x\\\\ \]

于是显然有

\[k^tx\equiv x(\bmod y)=>k^t\equiv 1(\bmod y)\\\\ k^t\equiv 1^t(\bmod y),k>0,1>0=>k\equiv 1(\bmod y)\\\\ \]

所以有:

\[\gcd(k,y)=1 \]

(这里一开始推到 \(y|(k-1)\) 去了……我有问题)

这样就可以写出式子了:

\[\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=1][\gcd(j,k)=1] \]

然后就照常推理:

\[\begin{aligned} \sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=1][\gcd(j,k)=1] &=\sum_{j=1}^m[\gcd(j,k)=1]\sum_{i=1}^n[\gcd(i,j)=1]\\\\ &=\sum_{j=1}^m[\gcd(j,k)=1]\sum_{i=1}^n\sum_{d|\gcd(i,j)}\mu(d)\\\\ &=\sum_{d=1}^n\mu(d)\sum_{j=1}^{\lfloor m/d\rfloor}[\gcd(jd,k)=1]\sum_{i=1}^{\lfloor n/d\rfloor}\\\\ &=\sum_{d=1}^n\mu(d)\Big\lfloor \frac{n}{d}\Big\rfloor \sum_{j=1}^{\lfloor m/d\rfloor}[\gcd(jd,k)=1]\\\\ \end{aligned} \]

显然,这个式子应该尽量表示成两个不相关的式子乘积,注意到 \(k\) 是个常量,于是有

\[\sum_{d=1}^n\mu(d)\Big\lfloor \frac{n}{d}\Big\rfloor [\gcd(d,k)=1]\sum_{j=1}^{\lfloor m/d\rfloor}[\gcd(j,k)=1] \]

\[F(n)=\sum_{d=1}^n\mu(d)[\gcd(d,k)=1],G(n)=\sum_{j=1}^{n}[\gcd(j,k)=1] \]

(本来这里的 \(F\) 是带了一个 $\Big\lfloor \dfrac{n}{d}\Big\rfloor $ 的项……但是后来发现这是一个巨大的错误……总之很累赘,所以就没有带,反正最后是要整除分块的,这一项没什么用处)

然后就可以分开考虑了。

\[\begin{aligned} F(n)&=\sum_{i=1}^n\mu(i)[\gcd(i,k)=1]\\\\ &=\sum_{i=1}^n\mu(i) \sum_{d|\gcd(i,k)}\mu(d)\\\\ &=\sum_{i=1}^n\mu(i) \sum_{d|k}\mu(d)[d|i]\\\\ &=\sum_{d|k}\mu(d)\sum_{i=1}^{\lfloor n/d\rfloor}\mu(id)\\\\ \end{aligned} \]

暴毙了,不会搞了 /kk

……哦,对哦,显然还可以再套一个 \([\gcd(i,d)=1]\) .不然这个 \(\mu(id)\) 就没了。

这不是更复杂了吗 并不,因为 \(\mu\) 可是积性函数呢 /xyx

\[\begin{aligned} F(n)&=\sum_{d|k}\mu(d)\sum_{i=1}^{\lfloor n/d\rfloor}\mu(id)\\\\ &=\sum_{d|k}\mu(d)\sum_{i=1}^{\lfloor n/d\rfloor}\mu(i)\mu(d)[\gcd(i,d)=1]\\\\ &=\sum_{d|k}\mu(d)^2\sum_{i=1}^{\lfloor n/d\rfloor} \mu(i)[\gcd(i,d)=1]\\\\ \end{aligned} \]

掉线了掉线了,又不会推了 /kel . 虽然这个 \(\gcd\) 还可以拆但是 \(d\) 的范围也降不下来了啊。

正在重连……连接失败 . 呜呼!

。去看具体数学了。下午再来推这个。

我回来了!我发现上午人傻掉了。

让我们把最初的样子和最后的结果放在一起,带上一个 \(k\) 的参数:

\[F(n,k)=\sum_{d=1}^n\mu(d)[\gcd(d,k)=1]\\\\ F(n,k)=\sum_{d|k}\mu(d)^2\sum_{i=1}^{\lfloor n/d\rfloor} \mu(i)[\gcd(i,d)=1]\\\\ \]

发现下面式子的后半部分就是 \(F(\lfloor \frac{n}{d}\rfloor,d)\) !也就是说可以直接递归计算,然后加个记忆化, \(F(n)\) 就做完了。

边界为 \(F(n,1)\) ,杜教筛就好了。筛它就完了!

什么?前面一半漏了?\(k\leq 2000\) 啊,随便跑跑就行了。

下面来看 \(G(n)\) .

\[G(n)=\sum_{j=1}^{n}[\gcd(j,k)=1]=\Big\lfloor \frac{n}{k}\Big\rfloor \varphi(k) \]

没了!这是好的!

那么答案就是:

\[Ans=\sum_{d=1}^n\mu(d)[\gcd(d,k)=1]G(\lfloor \frac md\rfloor)\cdot \Big\lfloor \frac{n}{d}\Big\rfloor \]

整除分块就没了 awa.

注意分子和分母不一样,所以不能 swap(n,m) .

Code

posted @ 2020-12-25 15:33  MontesquieuE  阅读(196)  评论(1编辑  收藏  举报