积性函数的性质及证明 + 线性筛

来源:互联网 发布:淘宝食品备案流程图 编辑:程序博客网 时间:2024/04/30 05:26

引言

在数论问题中,积性函数有着广泛的应用。
如在莫比乌斯反演问题中,函数变换之后如何快速维护前缀和往往是最重要也是最难的一步。如果维护的函数具有积性,那就可以尝试利用线性筛在O(n)的时限内完成预处理,从而达到优化复杂度的神奇作用。
本文的大部分相关性质及公式来自:
线
博主将试着证明其中的性质公式,严谨性可能欠缺,其目的主要是帮助记忆和理解
因水平有限 若有错误之处还望指出qwq~


积性函数的定义和性质

定义: 对于一个定义域为N+的函数f,对于任意两个互质的正整数a,b,均满足f(ab)=f(a)f(b),则称函数f为积性函数
若对于任意整数a,b都有f(ab)=f(a)f(b),则函数f被称为完全积性函数。

性质
(1)对于任意积性函数f均有f(1)=1

证明:因1与任何数都互质,假设存在一个正整数a满足f(a)!=0,故由定义:

f(a)=f(1a)=f(1)f(a)

f(a)不为0,故等号两端同时消去一个f(a),得:
f(1)=1

证毕。

(2)对于一个大于1的正整数N,N=paiipi为互不相同的素数。那么对于一个积性函数f来说,有:

f(N)=f(paii)=f(paii)

f完全积性,则
f(N)=f(pi)ai

证明:由积性和完全积性的定义易得。


欧拉函数φ

定义:对于正整数nφ(n)是小于n的正整数中与n互质的个数。

定义式:若n=paii

φ(n)=n(11pi)

性质
(1)欧拉函数为积性函数,而不是完全积性函数。

证明:设两个互质的正整数n,m
则:
φ(n)=n(11pi)
φ(m)=m(11pi)
φ(n)φ(m)=n(11pi)m(11pi)=nm(11pi)(11pi)
n,m互质,故 pi,pi 各不相同,且均为nm的质因子。

故推出:
φ(nm)=φ(n)φ(m)
积性函数性质得证。
而完全积性由上证明可见,n,m互质是一个严格且不可或缺的条件,可见,欧拉函数不是完全积性函数。

(2)假设存在一个素数p和一个正整数k则:φ(pk)=pkpk1
证明:

可以从反面来思考这件事,在小于pk且与其不互质的数有以下形式:
p1,p2,...p(pk11)(因为p是唯一的质因子)
故由定义:φ(pk)=总数 - 不互质的数 = (pk1)(pk11)=pkpk1
证毕。

另外还可以从定义式出发去理解这个结论。

φ(pk)=pk(11p)=pkpk1

(3)欧拉定理:若有互质的两个正整数a,n则有aφ(n)1(mod n)
此定理常用来求解逆元。

证明:(可参考百度百科)

(4)假设存在一个正整数n,则:d|nφ(d)=n

证明:
先考虑特殊情况: n=1φ(1)=1 显然成立
对于一般情况,n一定可以质因数分解为:n=pa11pa22...pakk

当n只含一个质因子时,即n=pa
有:

d|nφ(d)=i=0aφ(pi)=1+i=1a(pipi1)=1+i=1a(pi1+pi)

显然,将求和式展开,会有一些项可以合并。
比如a=3时,原式等于:

1p0+p1p1+p2p2+p3=p3

可见:
d|nφ(d)=i=0aφ(pi)=pa=n

n含多个质因子时,即n=pa11pa22...pakk
利用积性函数的性质有

d|nφ(d)=i=0a1φ(pi1)i=0a2ϕ(pi2)......i=0akφ(pik)

同上易得:

=pa11pa22......pakk=n

证毕。

(5)当n>1小于n且与n互质的数之和为

sum=nφ(n)2

证明:在数论求gcd中,有两个非常出名的公式,基于这两个公式,出现了两种快速求gcd的方法,更相减损法和辗转相除法。这两个公式是:(假设有两个正整数a,b且满足 a>b)
gcd(a,b)=gcd(a,ab)gcd(a,b)=gcd(b,a%b)

由第一个公式,知:
mn互质,则nm也一定与n互质。
这样就能将保证当n>2时,φ(n)一定为偶数,且可两两配对,每一对的和都是n

sum=nφ(n)2

n=2时,代入验证知,此公式依然满足。

证毕。

例题:HDU 3501
题意:求小于n且与n不互质的数之和。
思路:直接利用公式求反面,总数 - 反面数即为答案。
代码:

#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>using namespace std;typedef long long ll;const int mod = 1000000007;const int A = 1e5 + 10;bool vis[A];int pri[A],tot;void init(){    tot = 0;    vis[0] = vis[1] = 1;    for(int i=2 ;i<A ;i++){        if(vis[i] == 0) pri[++tot] = i;        for(int j=1 ;j<=tot&&pri[j]*i<A ;j++){            vis[pri[j]*i] = 1;            if(i%pri[j] == 0) break;        }    }}int main(){    init();    ll n;    while(~scanf("%I64d",&n) && n){        ll ans = (n*(n-1)/2)%mod;        ll res = n,m = n;        for(int i=1 ;i<=tot&&pri[i]*pri[i]<=n ;i++){            if(n%pri[i] == 0){                res = res/pri[i]*(pri[i]-1);                while(n%pri[i] == 0) n/=pri[i];            }        }        if(n!=1) res = res/n*(n-1);        ans = ans - res*m/2;        printf("%I64d\n",(ans%mod+mod)%mod);    }    return 0;}

莫比乌斯函数μ

定义式:

μ(n)=1(1)k0(n=1)(n=p1p2...pk)(else)

性质:
(1)对于任意正整数n,有:

d|nμ(d)=[n==1]

该性质在莫比乌斯反演中有着极大应用。

证明:
n=1时 等式显然成立。
n>1时,令n=pa11pa22pa33...pakk
考虑莫比乌斯函数取值的特殊性,若函数值不为0,则d只含每个质因子的0次或1次项。

d|nμ(d)=C0kC1k+C2k...+(1)kCkk=i=0k(1)iCik

由二项式定理,原式等于:

i=0k(1)iCik=i=0kCik(1)i(1)ki=(1+1)k=0

综上所述:
n=1原式为1
n>1原式为0
证毕。

(2)对于任意正整数n有:

d|nμ(d)d=φ(n)n

证明:
f(n)满足:f(n)=d|nφ(d)

由欧拉函数的性质(4)f(n)=n
又由莫比乌斯反演:

φ(n)=d|nμ(d)f(nd)

推出:
φ(n)=d|nnμ(d)d=nd|nμ(d)d

等式两边同除以n,得:

φ(n)n=d|nμ(d)d

证毕。


线性筛求积性函数

欧拉函数φ

考虑将所有数分成三类:
(1)质数 φ(i)=i1

(2)最小质因子指数为1:φ(ip)=φ(i)φ(p)

(3)最小质因子指数大于1:φ(ip)=pφ(i)(可从欧拉函数的定义式出发)

代码:

void init(){    tot = 0;phi[1] = 1;    for(int i=2 ;i<A ;i++){        if(!vis[i]){pri[++tot] = i;phi[i] = i-1;}        for(int j=1 ;j<=tot&&i*pri[j]<A ;j++){            vis[i*pri[j]] = 1;            if(i%pri[j] == 0){                phi[i*pri[j]] = pri[j] * phi[i];break;            }            phi[i*pri[j]] = phi[pri[j]] * phi[i];        }    }}

莫比乌斯函数μ

因为线性筛每次都是用最小质因子去筛每一个数。
故也可分为三类:
(1)i为质数:μ[i]=1

(2)i已经包含最小质因子pμ[ip]=0

(3)i不包含最小质因子pμ[ip]=μ[i]

代码:

void init(){    tot = 0;mu[1] = 1;    for(int i=2 ;i<A ;i++){        if(!vis[i]){pri[++tot] = i;mu[i] = -1;}        for(int j=1 ;j<=tot&&i*pri[j]<A ;j++){            vis[i*pri[j]] = 1;            if(i%pri[j] == 0){mu[i*pri[j]] = 0;break;}            mu[i*pri[j]] = -mu[i];        }    }}

以下为其他常见积性函数的线性筛:

约数个数函数d

仍然分三类讨论,此时我们还需要维护每一个数i最小质因子的指数cnt[i]
(1)i为质数:d[i]=2 cnt[i]=1

(2)i已经包含最小质因子p
d[ip]=d[i]/(cnt[i]+1)(cnt[i]+2)(由约数个数公式易得)
cnt[ip]=cnt[i]+1

(3)i不包含最小质因子p
d[ip]=d[i](cnt[p]+1)=d[i]2
cnt[ip]=1

代码:

void init(){    tot = 0;d[1] = 1;    for(int i=2 ;i<A ;i++){        if(!vis[i]){pri[++tot] = i;d[i] = 2;cnt[i] = 1;}        for(int j=1 ;j<=tot&&i*pri[j]<A ;j++){            vis[i*pri[j]] = 1;            if(i%pri[j] == 0){                d[i*pri[j]] = d[i]/(cnt[i]+1)*(cnt[i]+2);                cnt[i*pri[j]] = cnt[i] + 1;                break;            }            d[i*pri[j]] = d[i]<<1;            cnt[i*pri[j]] = 1;        }    }}

约数和函数σ

假设一个正整数n分解质因子之后为:
n=pa11pa22pa33...pakk

σ(n)=i=0a1pi1i=0a2pi2.....i=0akpik

假设最小质因子为p1故线性筛中每一个被筛到的数比起原来的数,差别只在于:a1i=0pi1

故我们可以维护两个量:
sum[i]:i的最小质因子p1贡献的和:a1i=0pi1
Mx[i]: pa11a1 为最小质因子的最高次数。

然后又可以把所有数分成三类:
(1)i为质数:σ[i]=i+1 sum[i]=i+1 Mx[i]=i

(2)i已经包含最小质因子pσ[ip]=σ[i]/sum[i](sum[i]+Mx[i]p)
sum[ip]=sum[i]+Mx[i]p
Mx[ip]=Mx[i]p

(3)i不包含最小质因子pσ[ip]=σ[i]σ[p]=σ[i](p+1)
sum[ip]=p+1
Mx[ip]=p

代码:

void init(){    tot = 0;Sigma[1] = 1;    for(int i=2 ;i<A ;i++){        if(!vis[i]){            pri[++tot] = i;            Sigma[i] = 1 + i;            sum[i] = 1 + i;            Mx[i] = i;        }        for(int j=1 ;j<=tot&&i*pri[j]<A ;j++){            vis[i*pri[j]] = 1;            if(i%pri[j] == 0){                Sigma[i*pri[j]] = Sigma[i]/sum[i]*(sum[i] + Mx[i]*pri[j]);                sum[i*pri[j]] = sum[i] + Mx[i]*pri[j];                Mx[i*pri[j]] = Mx[i]*pri[j];                break;            }            Sigma[i*pri[j]] = Sigma[i]*(pri[j] + 1);            sum[i*pri[j]] = pri[j] + 1;            Mx[i*pri[j]] = pri[j];        }    }}
原创粉丝点击