前言
本文內容大部分來自Oier PoPoQQQ 的課件。\
onedrive, baidu
pan,密碼:6ug5\
本文基本上由我學習相當於是制作的一篇學習筆記,但是將課件中的一些不完善的地方加以完善
使得更容易理解,加上了部分例題的代碼
引子
介紹莫比烏斯反演之前我們先來看一個函數
根據 的定義
於是我們便可以通過 推導出
在推導的過程中我們是否發現了一些規律?
莫比烏斯反演
莫比烏斯反演[1]
莫比烏斯反演定義
其中 為莫比烏斯函數[1],定義如下
莫比烏斯函數的定義式[2]
莫比烏斯函數的性質
(1)
當n不等於1時,n所有因子的莫比烏斯函數值的和為0,\
設
那么
證明:
(2)
對於 有:
(3)
積性函數 數論上積性函數的定義\
積性函數的性質\
\
積性函數的前綴和也是積性函數\
\
因為積性函數是積性函數,
因此可以通過線性篩求出莫比烏斯函數的值
mu[1]=1;
for(i=2;i<=n;i++){
if(!not_prime[i]){
prime[++tot]=i;
mu[i]=-1;
}
for(j=1;prime[j]*i<=n;j++){
not_prime[prime[j]*i]=1;
if(i%prime[j]==0){
mu[prime[j]*i]=0;
break;
}
mu[prime[j]*i]=-mu[i];
}
}
例題1:
題目大意:求第k個無平方因子數[3]\
做法:
首先二分答案,問題轉化為求
之間有多少個無平方因子數\
根據容斥原理可知,對於
之內所有的質數,
答案G(x)=0個質數平方倍數的個數-1個質數平方倍數的個數+2個質數平方倍數的個數-...,
那么對於偶數個質數平方對於答案的貢獻就是正的,否則是負的,\
如果不是若干個互異質數的乘積,那么對答案沒有影響,
如何表示這個式子呢?\
觀察莫比烏斯函數的定義[1],可以知道對於能對答案產生貢獻的數
,
,其中
為
分解得到質數的個數
根據上述說明,那么可以得知結果\
#include<iostream> #include<cstdio> #include<cmath> #define N 100005 using namespace std;
bool not_prime[N];
int prime[N];
int mu[N];
int tot;void Mu(int n){
int i,j;
mu[1]=1;
for(i=2;i<=n;i++){
if(!not_prime[i]){
prime[++tot]=i;
mu[i]=-1;
}
for(j=1;prime[j]i<=n;j++){
not_prime[prime[j]i]=1;
if(i%prime[j]==0){
mu[prime[j]i]=0;
break;
}
mu[prime[j]i]=-mu[i];
}
}
}
int can(int x){
int sum=0;
int s=floor(sqrt(x));
for(int i=1;i<=s;++i)
if(mu[i])
sum+=mu[i]floor(x/(ii));
return sum;
}
int main(){
Mu(N);int T,sum;
scanf("%d",&T);
while(T--){
scanf("%d",&num);
long long l=1,r=num<<1,mid;
while(l<r){
mid=(l+r)>>1;
if(can(mid)<num)
l=mid+1;
else r=mid;
}
printf("%lld\n",r);
}
return 0;
}
莫比烏斯反演定理的證明
證明:
形式二:
證明同理,一般要用到的都是這種形式
莫比烏斯反演的應用
對於一些函數
,如果我們很難直接求出它的值,而容易求出倍數和或約數和
,
那么我們可以直接利用莫比烏斯反演來求得
的值
例:
f(n)表示某一范圍內(x,y)=n的數對的數量,\
F(n)表示某一范圍內n|(x,y)的數對的數量\
那么直接求f(n)並不是很好求,而F(n)求起來相對無腦一些,\
那么我們可以通過對F(n)進行莫比烏斯 反演來求得f(n)</p>
例題2:
題目大意:詢問有多少對 滿足 且 。
根據容斥原理,這個題目就可以轉化成
其中答案為 </p>
那么我們需要快速求出
這個式子可以進一步轉化為
考慮莫比烏斯反演, 令
分析可知這個算法的復雜度是
我們還需要對這個算法進行進一步優化
因為 至多只有 個取值,
那么 至多只有 個取值
因為使得 成立的 值都是連續的,
所以可以維護一個莫比烏斯函數的前綴和,
這樣就可以在 的時間內出解
枚舉除法的取值在莫比烏斯反演的應用當中非常常用
if(a>b)swap(a,b);
for(i=1;i<=a;i=last+1){
last=min(a/(a/i),b/(b/i));
re+=(a/i)(a/i)(sum[last]-sum[i-1]);
}
return re;
代碼異常好寫
#include<iostream>
include<cstdio>
include<cmath>
define N 50005
define inf 0x7fffffff
using namespace std;
bool not_prime[N];
int prime[N];
int sum[N];
int mu[N];
int tot;void Mu(int n){
int i,j;
mu[1]=1;
for(i=2;i<=n;i++){
if(!not_prime[i]){
prime[++tot]=i;
mu[i]=-1;
}
for(j=1;prime[j]i<=n;j++){
not_prime[prime[j]i]=1;
if(i%prime[j]==0){
mu[prime[j]i]=0;
break;
}
mu[prime[j]i]=-mu[i];
}
}
for(int i=1;i<=n;++i)
sum[i]=sum[i-1]+mu[i];
}
int ans(int n,int m){
if(n>m)swap(n,m);
int last,i,re=0;
for(i=1;i<=n;i=last+1){
last=min(n/(n/i),m/(m/i));
re+=(n/i)(m/i)(sum[last]-sum[i-1]);
}
return re;
}
int main(){
Mu(N);
int T;
int a,b,c,d,k;
scanf("%d",&T);
while(T--){
scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
a--;c--;
a/=k;b/=k;c/=k;d/=k;
int Ans=ans(b,d)-ans(a,d)-ans(b,c)+ans(a,c);
printf("%d\n",Ans);
}
return 0;
}
BZOJ 10s但是luogu卻莫名WA\
全部加上long long 之后總算是過了\
百思不得其解
例題3
BZOJ 2820
YY的GCD\
題目大意:求有多少數對
滿足
滿足
為質數
做法: