1. 程式人生 > 實用技巧 >從1開始的數論 2

從1開始的數論 2

整除分塊

1.對於我們之前介紹過的特殊點 [n/d]我們可以發現,在一道完整的序列上,其中每一段連續的塊上的特殊點的值是相等的,換而言之,他是按照塊狀分佈的

2.通過打表之類的各種方法,我們驚喜的發現對於每一個值相同的塊,它的最後一個數就是n/(n/i)n/(n/i)。得出這個結論後,我們就可以做的O(n−−√)O(n)處理了。

假設我們需要求的是Σ(1-n) [n/i]

那麼我們可以得到如下的程式碼

#include <stdio.h>

using namespace std;

int n,ans=0;

int main()
{
    scanf(
"%d", &n); for(int l = 1, r;l <= n; l = r + 1) { r=n/(n/l);printf("%d ", r); ans+=(r-l+1)*(n/l); } printf("\n%d",ans); return 0; }
View Code

以10為例,分界點就是1 2 3 5 10;

題目 3:求無平方因子數的個數

對於積性函式我們不妨來總結一下:

常見積性函式

  1. μ(n)μ(n)——莫比烏斯函式。關於這個函式,我在莫比烏斯反演中說的挺清楚的了(233),(PS:不過我將會在下文中,從另一種角度介紹它的性質。也算是把坑給填完吧)
  2. φ(n)φ(n)——尤拉函式。表示不大於nn且與nn互質的正整數個數,十分常見的數論函式。用數學式子表示即:φ(n)=ni=1[(n,i)=1]φ(n)=∑i=1n[(n,i)=1](PS:(n,i)(n,i)表示gcd(n,i)gcd(n,i))
  3. d(n)d(n)——約數個數。表示nn的約數的個數。用式子表示為:d(n)=d|n1d(n)=∑d|n1,也可以寫作:d(n)=nd=1[d|n]d(n)=∑d=1n[d|n](其實沒什麼太大區別啦!)
  4. σ(n)
    σ(n)——約數和函式。 即nn的各個約數之和。表示為:σ(n)=d|nd=nd=1[d|n]dσ(n)=∑d|nd=∑d=1n[d|n]⋅d

(PS:接下來列舉的是完全積性函式)
(PS:代表字母可能會與他人的略有不同,似乎在數學中沒有統一的字母)

    1. ϵ(n)ϵ(n)——元函式。似乎也有人把它叫作e(n)e(n)?其實無所謂啦~~我們只需要知道ϵ(n)=[n=1]ϵ(n)=[n=1]。(看到這個是不是有種莫名的熟悉感呢?到了下文中,就會發現這種熟悉感是從哪來的啦!)
    2. I(n)I(n)——恆等函式。所謂恆等就是這個函式的值恆為11。
    3. id(n)id(n)——單位函式。id(n)=nid(n)=n

【PS:注意尤拉和mobiwus的特殊性質】

13.杜教篩

PS:特別要記住一點:積性函式有一個特別重要的性質,那就是(積性函式∗積性函式)仍然為積性函式!!!這個性質可以用來判斷能否被杜教篩
利用狄利克雷卷積來構造遞推式,對一些數論的函式進行快速的求和(平常的演算法就是使用線性篩法來O(n)
1.求Σ(1-n)φ(n) 因為有尤拉函式 自然考慮 id = φ * 1;

我們來進行一下推導 假設

然後 因為id=n,我們自然聯想到自然數的求和 =

接下來 ,我們就要在結果當中尋找我們需要的東西

後面那個東西是子問題,可以遞迴解決【跟斐波那契一樣,我們需要使用記憶化實現,計算特殊點處的函式值】

3.時間複雜度:特殊點的結構是在(1-跟n和跟n到n兩個之間)