杜教篩 [學習筆記]【更新中】


杜教篩

嘟嘟嘟


tangjz orz

jiry_2 orz

任之洲 2016國家隊論文 orz


概述

前置技能:莫比烏斯反演

可以在\(O(\frac{3}{4})\)\(O(\frac{2}{3})\)復雜度完成數論函數(前綴和)的計算


一般形式

數論函數\(f(n)\),求

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

對於任意數論函數\(g(n)\),均滿足

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

\(Proof.\)

\[\begin{align*} \sum_{i=1}^n (f*g)(i) &= \sum_{i=1}^n \sum_{d\mid i} f(d) g(\frac{i}{d}) \\ 先枚舉幾倍再枚舉約數 \\ &= \sum_{i=1}^n g(i) \sum_{d=1}^{\lfloor \frac{n}{d} \rfloor}f(d) \\ &= \sum_{i=1}^n g(i) S(\lfloor \frac{n}{d} \rfloor) \end{align*} \]

  • 注意枚舉幾倍的技巧:對於i*j=k,我們枚舉了i和j

這樣的話可以得到

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

通常情況\(g(1)=1\)

這個柿子可以整除分塊

找到合適的\(g\)

如果能通過狄利克雷卷積構造一個更好計算前綴和的函數,且用於卷積的另一個函數也易計算,則可以簡化計算過程


時間復雜度

假設計算出\(ϕ(n)\)的復雜度為\(T(n)\),則有\(T(n)=O(\sqrt{n})+\sum_{i=1}^{\sqrt{n}}{T(i)+T(\frac{n}{i})}\)這里只展開一層就可以了,更深層的復雜度是高階小量,所以有\(T(n)=\sum_{i=1}^{\sqrt{n}}{O(\sqrt{i})+O(\sqrt{\frac{n}{i}})}=O(n^\frac{3}{4})\)

預處理前k個的答案后,\(T(n)=\sum_{i=1}^{\frac{n}{k}}{\sqrt{\frac{n}{i}}}=O(\frac{n}{\sqrt{k}})\),\(k=O(n^\frac{2}{3})\)時最優\(T(n)=O(n^\frac{2}{3})\)


基本形式

  • 基本形式只是為了簡化思考,用一般形式找函數卷上均可以完成
  • 就是說沒大有用啦

一. 數論函數\(f(n)\),完全積性函數\(g(n)\),求

\[S(n)=\sum_{i=1}^n(f \cdot g)(i) \]

此時滿足

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

\(Proof.\)

\[\begin{align*} \sum_{i=1}^n {((f*1) \cdot g)(i)} &= \sum_{i=1}^n g(i) \sum_{d\mid i} f(d) \\ 先枚舉幾倍 \\ &= \sum_{i=1}^n \sum_{d=1}^{\lfloor \frac{n}{i} \rfloor} f(d) g(id) \\ 因為g(id)=g(i)\cdot g(d) \\ &= \sum_{i=1}^n g(i) S(\lfloor \frac{n}{d} \rfloor) \end{align*} \]

也就是說這種情況我們只要讓另一個函數卷\(1\),完全積性函數直接當做我們找的函數。


二. 待填坑




簡單的栗子

都是卷上\(1\)

一. 求\(\mu\)的前綴和

\[\mu * 1 = \epsilon \\ S(n) = 1 - \sum_{i=2}^n S(\lfloor \frac{n}{i} \rfloor) \]

二. 求\(\varphi\)的前綴和

\[\phi * 1 = id \\ S(n) = \frac{n(n+1)}{2} - \sum_{i=2}^n S(\lfloor \frac{n}{i} \rfloor) \]


代碼實現

使用記憶化搜索和哈希表

//這是phi前綴和。首先要線性篩預處理一部分。
namespace ha {
	const int p = 1001001;
	struct meow{int ne; ll val, r;} e[3000];
	int cnt=1, h[p];
	inline void insert(ll x, ll val) {
		ll u = x % p;
		for(int i=h[u];i;i=e[i].ne) if(e[i].r == x) return;
		e[++cnt] = (meow){h[u], val, x}; h[u] = cnt;
	}
	inline ll quer(ll x) {
		ll u = x % p;
		for(int i=h[u];i;i=e[i].ne) if(e[i].r == x) return e[i].val;
		return -1;
	}
} using ha::insert; using ha::quer;

ll dj_sieve(ll n) {
	if(n <= U) return phi[n];
	if(quer(n) != -1) return quer(n);
	ll ans = n%mo * ((n+1) %mo) %mo * inv2 %mo, r;
	for(ll i=2; i<=n; i=r+1) {
		r = n/(n/i);
		mod(ans -= dj_sieve(n/i) * ((r-i+1) %mo) %mo);
	}
	insert(n, ans);
	return ans;
}

栗子

一. 求 \(\sum_{i=1}^n \sum_{j=1}^n lcm(i, j)\)

有兩類做法。

一.變成積性函數求和的形式

首先進行化簡

\[\begin{align*} A(n) &= \sum_{i=1}^nlcm(i,n)=n \sum_{i=1}^n\frac{i}{(n,i)} \\ &=n \sum_{d\mid n}\sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}i[(\frac{n}{d}, i)=1] \\ &= \frac{1}{2} n (1 + \sum_{d\mid n}d \cdot \varphi(d)) \end{align*} \]

\(ans = 2*A(n) - \sum_{i=1}^n\)

就是\(f(n) = n\sum_{d\mid n}d \cdot \varphi(d)= id \cdot ((id \cdot \varphi) * 1)\)的前綴和。

  • 其中重要的一步在於使用歐拉函數的性質代入,而不是使用莫比烏斯函數代入

這里又有兩種做法。


法一:

\[\begin{align*} ans &= \sum_{i=1}^n i \sum_{d\mid i}d \cdot \varphi(d) \\ 先枚舉幾倍 \\ &= \sum_{i=1}^n i \sum_{d=1}^{\lfloor \frac{n}{i} \rfloor} d^2 \cdot \varphi(d) \end{align*} \]

后面是可以整除分塊的形式,我們只要處理出\(i^2 \cdot \varphi(i)=(id^2 \cdot \varphi)(i)\)的前綴和\(S(n)\)就行了

\(id^2\)是完全積性函數,滿足杜教篩基本形式一,單獨讓\(\varphi\)卷上\(1\),也變成\(id\)了。

或者直接卷上\(id^2\),效果相同

\[S(n) = \sum_{i=1}^n i^3 - \sum_{i=2}^n i^2 S(\lfloor \frac{n}{i} \rfloor) \]

其中\(\sum_{i=1}^{n} i^3 = (\frac{n(n+1)}{2})^2,\ \sum_{i=1}^{n} i^2 = \frac{n(n+1)(2n+1)}{6}\)


杜教篩的過程中計算了所有\(S(\lfloor \frac{n}{i} \rfloor)\),可以和整除分塊配合食用


法二:

把f外面的n拿進來

直接計算\(f(n) = id \cdot ((id \cdot \varphi) * 1) = (id^2 \cdot \varphi) * id\)的前綴和。

卷上\(id^2\)

\[((id^2 \cdot \varphi) * id^2) * id = id^3 * id \\ S(n) = \sum_{i=1}^n (id^3 * id)(i) - \sum_{i=2}^n i^2 S(\lfloor \frac{n}{i} \rfloor) \]

前部分的前綴和可以用整除分塊解決

使用線性篩直接預處理S的前\(n^{\frac{2}{3}}\)項,只要預處理\((id \cdot \varphi) * 1 = \sum_{d\mid n}d \cdot \varphi(d)\)就行了,因為是點乘比較好做。\(p^c\)的形式處理出來,剩下的保留最小質因子的冪次然后用積性。


二.使用莫比烏斯反演的套路

abclzr的博客發現了這種做法:

套路推♂倒之后得到的柿子是:

\[\sum_{i=1}^n \frac{\lfloor \frac{n}{i} \rfloor(\lfloor \frac{n}{i} \rfloor+1)}{2} \frac{\lfloor \frac{m}{i} \rfloor(\lfloor \frac{m}{i} \rfloor+1)}{2} i \sum_{d\mid i} d\cdot \mu(d) \]

我們只需用杜教篩計算\(i \sum_{d\mid i} d\cdot \mu(d)\)的前綴和,然后與整除分塊配合就行了(因為每次塊的r的值也是一個\(\frac{n}{i}\)的值)

就是要計算\(f=(id^2 \cdot \mu) * id\)的前綴和,卷上\(id^2\)后變成\(f(n) = n\sum_{d\mid n}[d=1]=n\)

上杜教篩就行了

預處理的話,可以用線性篩預處理\(f'=\sum_{d\mid n}d\cdot \mu(d)\),發現\(f'=\prod_i(1-p_i)\)

這樣做的好處是可以處理n和m的情況




總結

找到一個函數卷上方便求

莫比烏斯反演的題目一般是約數和倍數互換 令D=de,這里一般是約數與幾倍互換

TA:

對於d,e,D=d*e 三項貢獻的這種,可以枚舉D將其化為狄利克雷卷積,也可以枚舉d和e化成帶下取整的式子;一般來講前者往往易於預處理,可以應付多組詢問,后者則在單次詢問中有優秀表現。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM