数论 —— 莫比乌斯反演
生活随笔
收集整理的這篇文章主要介紹了
数论 —— 莫比乌斯反演
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
【反演】
假設我們手頭有個數列?F,通過某種變換 H,可以得到函數 G。,即:
但現在只有函數 G,需要求 F,那么我們就需要尋找一種變換 ,使得 G 在經過這種變換后能夠獲得 F,這個過程即為反演,即:
【整除分塊】
對于式子:,其時間復雜度為 O(n),當有多組數據時,O(n) 并非正確的時間復雜度,此時有一種時間復雜度為 O(√n) 的算法:整除分塊
對于每一個??通過打表發現,很多 ?的值是相同的,它們呈一個塊狀分布,對每一個值相同的塊,它的最后一個數是:
有時候,可能式子不一定是一個裸的整除分塊,可能會與某些積性函數相乘,這時就需要對這些函數統計一個前綴和。因為,每當我們使用整除分塊跳過一個區間的時候,其所對應的函數值也跳過了一個區間,所以就需要乘上那一個區間的函數值
實現
int res=0; for(int left=1,right;left<=n;left=right+1){right=n/(n/left);res+=(righr-left+1)*(n/left); }對于式子:,其時間復雜度為 O(n^2),同樣可以使用整除分塊的做法來降低時間復雜度
int res=0; int minn=min(n,m); for(int left=1,right;left<=minn;left=right+1){right=min(n/(n/left),m/(m/left));res+=(righr-left+1)*(n/left)*(m/left); }【莫比烏斯函數】
1.定義
其中對于??的情況,,且??均為互質素數
簡單來說,其滿足以下幾點:
- 定義域:N
- 當 d 為 1 時:μ(1)=1
- 當 d?是偶數個不同素數之積時:μ(d)=1
- 當 d?是奇數個不同素數之積時:μ(d)=-1
- 當 d 是素數時:μ(d)=-1
- 當 d?存在平方因子時:μ(d)=0
2.性質
- 莫比烏斯函數?μ(d) 為積性函數:μ(d) 可以線性篩
- 對于任意正整數 n,有:,當且僅當 n=1 時計數的函數,可用于求 (i,j)=1 的問題
- 對于任意正整數 n,有:,其中??為歐拉函數
3.實現
1)普通篩
int mu[N]; void getMu(){for(int i=1;i<N;++i)int target=(i==1?1:0);int delta=target-mu[i];mu[i]=delta;for(int j=2*i;j<N;j+=i)mu[j]+=delta;} }2)線性篩
int mu[N]; int prime[N]; bool bprime[N]; int cnt; void getMu(int n){//線性篩求莫比烏斯函數cnt=0;mu[1]=1;//根據定義,μ(1)=1memset(bprime,false,sizeof(bprime));for(int i=2;i<=n;i++){//求2~n的莫比烏斯函數if(!bprime[i]){prime[++cnt]=i;//存儲質數mu[i]=-1;//i為質數時,μ(1)=-1}for(int j=1;j<=cnt&&i*prime[j]<=n;j++){//枚舉i之前的素數個數bprime[i*prime[j]]=true;//不是質數if(i%prime[j])//i不是prime[j]的整數倍時,i*prime[j]就不會包含相同質因子mu[i*prime[j]]=-mu[i];//mu[k]=mu[i]*mu[prime[j]],因為prime[j]是質數,mu值為-1else{mu[i*prime[j]]=0;break;//留到后面再篩}}} }【莫比烏斯反演】
對于一些函數f(n),很難直接求出其值,但容易求出約數和或倍數和g(n),那么可以通過莫比烏斯反演來求得f(n)
莫比烏斯反演的題目通常能轉化為(x,y)=1的計數問題,即用f(n)表示某一范圍(x,y)=n的數對數量,g(n)表示某一范圍內n|(x,y)的數對數量。
1.形式1
?和??是定義在非負整數集合上的兩個函數,那么有:
2.形式2
?和??是定義在非負整數集合上的兩個函數,且滿足條件:
那么:
【例題】
總結
以上是生活随笔為你收集整理的数论 —— 莫比乌斯反演的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 分治 —— 莫队算法
- 下一篇: 字符串处理 —— 概述