在数论问题中,积性函数有着广泛的应用。
如在莫比乌斯反演问题中,函数变换之后如何快速维护前缀和往往是最重要也是最难的一步。如果维护的函数具有积性,那就可以尝试利用线性筛在 O ( n ) O(n) O(n)的时限内完成预处理,从而达到优化复杂度的神奇作用。
本文的大部分相关性质及公式来自:《线性筛与积性函数》- 贾志鹏
博主将试着证明其中的性质公式,严谨性可能欠缺,其目的主要是帮助大家理解并记忆。
定义: 对于一个定义域为 N + N^{+} N+的函数 f f f,对于任意两个互质的正整数 a , b a,b a,b,均满足 f ( a b ) = f ( a ) f ( b ) f(ab)=f(a)f(b) f(ab)=f(a)f(b),则称函数 f f f为积性函数
若对于任意整数 a , b a,b a,b都有 f ( a b ) = f ( a ) f ( b ) f(ab) = f(a)f(b) f(ab)=f(a)f(b),则函数 f f f被称为完全积性函数。
性质:
(1)对于任意积性函数 f f f,均有 f ( 1 ) = 1 f(1) = 1 f(1)=1
证明:因 1 1 1与任何数都互质,假设存在一个正整数 a a a满足 f ( a ) ! = 0 f(a)!=0 f(a)!=0,故由定义: f ( a ) = f ( 1 ∗ a ) = f ( 1 ) f ( a ) f(a) = f(1*a) = f(1)f(a) f(a)=f(1∗a)=f(1)f(a)
因 f ( a ) f(a) f(a)不为 0 0 0,故等号两端同时消去一个 f ( a ) f(a) f(a),得:
f ( 1 ) = 1 f(1) = 1 f(1)=1
证毕。
(2)对于一个大于 1 1 1的正整数N,设 N = ∏ p i a i N = \prod p_i^{a_i} N=∏piai, p i p_i pi为互不相同的素数。那么对于一个积性函数 f f f来说,有:
f ( N ) = f ( ∏ p i a i ) = ∏ f ( p i a i ) f(N) = f(\prod p_i^{a_i}) = \prod f(p_i^{a_i}) f(N)=f(∏piai)=∏f(piai)
若 f f f完全积性,则 f ( N ) = ∏ f ( p i ) a i f(N) = \prod f(p_i)^{a_i} f(N)=∏f(pi)ai
证明:由积性和完全积性的定义易得。
定义:对于正整数 n n n, φ ( n ) \varphi(n) φ(n)是小于n的正整数中与n互质的个数。
定义式:若 n = ∏ p i a i n = \prod p_i^{a_i} n=∏piai
φ ( n ) = n ∏ ( 1 − 1 p i ) \varphi(n) = n \prod(1 - \frac{1}{p_i}) φ(n)=n∏(1−pi1)
性质:
(1)欧拉函数为积性函数,而不是完全积性函数。
证明:设两个互质的正整数 n , m n,m n,m
则:
φ ( n ) = n ∏ ( 1 − 1 p i ) \varphi(n) = n \prod(1 - \frac{1}{p_i}) φ(n)=n∏(1−pi1)
φ ( m ) = m ∏ ( 1 − 1 p i ′ ) \varphi(m) =m \prod(1 - \frac{1}{p'_i}) φ(m)=m∏(1−pi′1)
φ ( n ) φ ( m ) = n ∏ ( 1 − 1 p i ) m ∏ ( 1 − 1 p i ′ ) = n m ∏ ( 1 − 1 p i ) ( 1 − 1 p i ′ ) \varphi(n)\varphi(m) = n \prod(1 - \frac{1}{p_i})m \prod(1 - \frac{1}{p'_i}) = nm\prod(1 - \frac{1}{p_i})(1 - \frac{1}{p'_i}) φ(n)φ(m)=n∏(1−pi1)m∏(1−pi′1)=nm∏(1−pi1)(1−pi′1)
因 n , m n,m n,m互质,故 p i , p i ′ p_i,p'_i pi,pi′ 各不相同,且均为 n m nm nm的质因子。
故推出:
φ ( n m ) = φ ( n ) φ ( m ) \varphi(nm) = \varphi(n)\varphi(m) φ(nm)=φ(n)φ(m)
积性函数性质得证。
而完全积性由上证明可见, n , m n,m n,m互质是一个严格且不可或缺的条件,可见,欧拉函数不是完全积性函数。
(2)假设存在一个素数 p p p和一个正整数 k k k,则: φ ( p k ) = p k − p k − 1 \varphi(p^k) = p^k - p^{k-1} φ(pk)=pk−pk−1
证明:
可以从反面来思考这件事,在小于 p k p^k pk且与其不互质的数有以下形式:
p ∗ 1 , p ∗ 2 , . . . p ∗ ( p k − 1 − 1 ) p*1,p*2,...p*(p^{k-1} - 1) p∗1,p∗2,...p∗(pk−1−1)(因为p是唯一的质因子)
故由定义: φ ( p k ) = \varphi(p^k) = φ(pk)=总数 - 不互质的数 = ( p k − 1 ) − ( p k − 1 − 1 ) = p k − p k − 1 (p^k-1) - (p^{k-1} -1) = p^k - p^{k-1} (pk−1)−(pk−1−1)=pk−pk−1
证毕。
另外还可以从定义式出发去理解这个结论。
φ ( p k ) = p k ( 1 − 1 p ) = p k − p k − 1 \varphi(p^k) = p^k(1-\frac{1}{p}) = p^k - p^{k-1} φ(pk)=pk(1−p1)=pk−pk−1
(3)欧拉定理:若有互质的两个正整数 a , n a,n a,n,则有 a φ ( n ) ≡ 1 ( m o d n ) a^{\varphi(n)} \equiv 1(mod \ n) aφ(n)≡1(mod n)
此定理常用来求解逆元。
证明:(可参考百度百科)
(4)假设存在一个正整数n,则: ∑ d ∣ n φ ( d ) = n \sum_{d|n} \varphi(d) = n ∑d∣nφ(d)=n
证明:
先考虑特殊情况: n = 1 n = 1 n=1时 φ ( 1 ) = 1 \varphi(1) = 1 φ(1)=1 显然成立
对于一般情况, n n n一定可以质因数分解为: n = p 1 a 1 p 2 a 2 . . . p k a k n = p_1^{a_1}p_2^{a_2}...p_k^{a_k} n=p1a1p2a2...pkak
当n只含一个质因子时,即 n = p a n = p^a n=pa
有:
∑ d ∣ n φ ( d ) = ∑ i = 0 a φ ( p i ) = 1 + ∑ i = 1 a ( p i − p i − 1 ) = 1 + ∑ i = 1 a ( − p i − 1 + p i ) \sum_{d|n}\varphi(d) = \sum_{i=0}^{a} \varphi(p^i) = 1 + \sum_{i=1}^{a}( p^i - p^{i-1}) = 1 + \sum_{i=1}^a(-p^{i-1} + p^i) d∣n∑φ(d)=i=0∑aφ(pi)=1+i=1∑a(pi−pi−1)=1+i=1∑a(−pi−1+pi)
显然,将求和式展开,会有一些项可以合并。
比如 a = 3 a = 3 a=3时,原式等于: 1 − p 0 + p 1 − p 1 + p 2 − p 2 + p 3 = p 3 1 - p^0 + p^1- p^1 + p^2 - p^2 + p^3 = p^3 1−p0+p1−p1+p2−p2+p3=p3
可见:
∑ d ∣ n φ ( d ) = ∑ i = 0 a φ ( p i ) = p a = n \sum_{d|n}\varphi(d) = \sum_{i=0}^a \varphi(p^i) = p^a = n d∣n∑φ(d)=i=0∑aφ(pi)=pa=n
当 n n n含多个质因子时,即 n = p 1 a 1 p 2 a 2 . . . p k a k n = p_1^{a_1}p_2^{a_2}...p_k^{a_k} n=p1a1p2a2...pkak
利用积性函数的性质有
∑ d ∣ n φ ( d ) = ∑ i = 0 a 1 φ ( p 1 i ) ∑ i = 0 a 2 ϕ ( p 2 i ) . . . . . . ∑ i = 0 a k φ ( p k i ) \sum_{d|n}\varphi(d) = \sum_{i=0}^{a_1} \varphi(p_1^i)\sum_{i=0}^{a_2} \phi(p_2^i) ...... \sum_{i=0}^{a_k} \varphi(p_k^i) d∣n∑φ(d)=i=0∑a1φ(p1i)i=0∑a2ϕ(p2i)......i=0∑akφ(pki)
同上易得:
原 式 = p 1 a 1 p 2 a 2 . . . . . . p k a k = n 原式=p_1^{a_1}p_2^{a_2} ...... p_k^{a_k} = n 原式=p1a1p2a2......pkak=n
证毕。
(5)当 n > 1 n>1 n>1,小于 n n n且与 n n n互质的数之和为 s u m = n φ ( n ) 2 sum = \frac{n\varphi(n)}{2} sum=2nφ(n)
证明:在数论求 g c d gcd gcd中,有两个非常出名的公式,基于这两个公式,出现了两种快速求 g c d gcd gcd的方法,更相减损法和辗转相除法。这两个公式是:(假设有两个正整数 a , b a,b a,b且满足 a > b a>b a>b)
g c d ( a , b ) = g c d ( a , a − b ) gcd(a,b) = gcd(a,a-b) gcd(a,b)=gcd(a,a−b) 和 g c d ( a , b ) = g c d ( b , a % b ) gcd(a,b) = gcd(b,a\%b) gcd(a,b)=gcd(b,a%b)
由第一个公式,知:
若 m m m与 n n n互质,则 n − m n-m n−m也一定与 n n n互质。
这样就能将保证当 n > 2 n>2 n>2时, φ ( n ) \varphi(n) φ(n)一定为偶数,且可两两配对,每一对的和都是 n n n。
故 s u m = n φ ( n ) 2 sum = n\frac{\varphi(n)}{2} sum=n2φ(n)
当 n = 2 n=2 n=2时,代入验证知,此公式依然满足。
证毕。
例题:HDU 3501
题意:求小于n且与n不互质的数之和。
思路:直接利用公式求反面,总数 - 反面数即为答案。
代码:
#include
#include
#include
#include
#include
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 ( n = 1 ) ( − 1 ) k ( n = p 1 p 2 . . . p k ) 0 ( e l s e ) \mu(n) = \begin{cases} 1 & (n=1)\\ (-1)^k&(n=p_1p_2...p_k)\\ 0&(else)\\ \end{cases} μ(n)=⎩⎪⎨⎪⎧1(−1)k0(n=1)(n=p1p2...pk)(else)
性质:
(1)对于任意正整数n,有:
∑ d ∣ n μ ( d ) = [ n = = 1 ] \sum_{d|n} \mu(d) = [n == 1] d∣n∑μ(d)=[n==1]
该性质在莫比乌斯反演中有着极大应用。
证明:
当 n = 1 n = 1 n=1时 等式显然成立。
当 n > 1 n>1 n>1时,令 n = p 1 a 1 p 2 a 2 p 3 a 3 . . . p k a k n = p_1^{a_1}p_2^{a_2}p_3^{a_3} ... p_k^{a_k} n=p1a1p2a2p3a3...pkak
考虑莫比乌斯函数取值的特殊性,若函数值不为 0 0 0,则d只含每个质因子的 0 0 0次或 1 1 1次项。
故 ∑ d ∣ n μ ( d ) = C k 0 − C k 1 + C k 2 . . . + ( − 1 ) k C k k = ∑ i = 0 k ( − 1 ) i C k i \sum_{d|n}\mu(d) = C_k^0 - C_k^1 + C_k^2 ...+(-1)^kC_k^k = \sum_{i=0}^k(-1)^iC_k^i d∣n∑μ(d)=Ck0−Ck1+Ck2...+(−1)kCkk=i=0∑k(−1)iCki
由二项式定理,原式等于:
∑ i = 0 k ( − 1 ) i C k i = ∑ i = 0 k C k i ( − 1 ) i ( 1 ) k − i = ( − 1 + 1 ) k = 0 \sum_{i=0}^k(-1)^iC_k^i = \sum_{i=0}^kC_k^i(-1)^i(1)^{k-i} = (-1 + 1)^k = 0 i=0∑k(−1)iCki=i=0∑kCki(−1)i(1)k−i=(−1+1)k=0
综上所述:
当 n = 1 n=1 n=1原式为 1 1 1
当 n > 1 n>1 n>1原式为 0 0 0
证毕。
(2)对于任意正整数 n n n,有:
∑ d ∣ n μ ( d ) d = φ ( n ) n \sum_{d|n}\frac{\mu(d)}{d} = \frac{\varphi(n)}{n} d∣n∑dμ(d)=nφ(n)
证明:
令 f ( n ) f(n) f(n)满足: f ( n ) = ∑ d ∣ n φ ( d ) f(n) = \sum_{d|n}\varphi(d) f(n)=∑d∣nφ(d)
由欧拉函数的性质 ( 4 ) (4) (4): f ( n ) = n f(n) = n f(n)=n
又由莫比乌斯反演: φ ( n ) = ∑ d ∣ n μ ( d ) f ( n d ) \varphi(n) = \sum_{d|n}\mu(d)f(\frac{n}{d}) φ(n)=d∣n∑μ(d)f(dn)
推出:
φ ( n ) = ∑ d ∣ n n μ ( d ) d = n ∑ d ∣ n μ ( d ) d \varphi(n) = \sum_{d|n}n\frac{\mu(d)}{d} = n \sum_{d|n} \frac{\mu(d)}{d} φ(n)=d∣n∑ndμ(d)=nd∣n∑dμ(d)
等式两边同除以n,得:
φ ( n ) n = ∑ d ∣ n μ ( d ) d \frac{\varphi(n)}{n} = \sum_{d|n}\frac{\mu(d)}{d} nφ(n)=d∣n∑dμ(d)
证毕。
考虑将所有数分成三类:
(1)质数 φ ( i ) = i − 1 \varphi(i) = i - 1 φ(i)=i−1
(2)最小质因子指数为1: φ ( i ∗ p ) = φ ( i ) φ ( p ) \varphi(i*p) = \varphi(i) \varphi(p) φ(i∗p)=φ(i)φ(p)
(3)最小质因子指数大于1: φ ( i ∗ p ) = p ∗ φ ( i ) \varphi(i*p) = p*\varphi(i) φ(i∗p)=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 i为质数: μ [ i ] = − 1 \mu[i] = -1 μ[i]=−1
(2) i i i已经包含最小质因子 p p p: μ [ i ∗ p ] = 0 \mu[i*p] = 0 μ[i∗p]=0
(3) i i i不包含最小质因子 p p p : μ [ i ∗ p ] = − μ [ i ] \mu[i*p] = -\mu[i] μ[i∗p]=−μ[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];
}
}
}
以下为其他常见积性函数的线性筛:
仍然分三类讨论,此时我们还需要维护每一个数 i i i最小质因子的指数 c n t [ i ] cnt[i] cnt[i]
(1) i i i为质数:$d[i] = 2 $ c n t [ i ] = 1 cnt[i] = 1 cnt[i]=1
(2) i i i已经包含最小质因子 p p p:
d [ i ∗ p ] = d [ i ] / ( c n t [ i ] + 1 ) ∗ ( c n t [ i ] + 2 ) d[i*p] = d[i]/(cnt[i]+1)*(cnt[i]+2) d[i∗p]=d[i]/(cnt[i]+1)∗(cnt[i]+2) (由约数个数公式易得)
c n t [ i ∗ p ] = c n t [ i ] + 1 cnt[i*p] = cnt[i] + 1 cnt[i∗p]=cnt[i]+1
(3) i i i不包含最小质因子 p p p :
d [ i ∗ p ] = d [ i ] ∗ ( c n t [ p ] + 1 ) = d [ i ] ∗ 2 d[i*p] = d[i]*(cnt[p] + 1) = d[i]*2 d[i∗p]=d[i]∗(cnt[p]+1)=d[i]∗2
c n t [ i ∗ p ] = 1 cnt[i*p] = 1 cnt[i∗p]=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 n分解质因子之后为:
n = p 1 a 1 p 2 a 2 p 3 a 3 . . . p k a k n = p_1^{a_1}p_2^{a_2}p_3^{a_3} ... p_k^{a_k} n=p1a1p2a2p3a3...pkak
则
σ ( n ) = ∑ i = 0 a 1 p 1 i ∑ i = 0 a 2 p 2 i . . . . . ∑ i = 0 a k p k i \sigma(n) = \sum_{i=0}^{a_1}p_1^i \sum_{i=0}^{a_2}p_2^i..... \sum_{i=0}^{a_k}p_k^i σ(n)=i=0∑a1p1ii=0∑a2p2i.....i=0∑akpki
假设最小质因子为 p 1 p_1 p1故线性筛中每一个被筛到的数比起原来的数,差别只在于: ∑ i = 0 a 1 p 1 i \sum_{i=0}^{a_1} p_1^i ∑i=0a1p1i
故我们可以维护两个量:
s u m [ i ] : i sum[i]:i sum[i]:i的最小质因子 p 1 p_1 p1贡献的和: ∑ i = 0 a 1 p 1 i \sum_{i=0}^{a_1} p_1^i ∑i=0a1p1i
M x [ i ] : Mx[i]: Mx[i]: p 1 a 1 p_1^{a_1} p1a1 a 1 a_1 a1 为最小质因子的最高次数。
然后又可以把所有数分成三类:
(1) i i i为质数: σ [ i ] = i + 1 \sigma[i] = i+1 σ[i]=i+1 s u m [ i ] = i + 1 sum[i] = i+1 sum[i]=i+1 M x [ i ] = i Mx[i] = i Mx[i]=i
(2) i i i已经包含最小质因子 p p p: σ [ i ∗ p ] = σ [ i ] / s u m [ i ] ∗ ( s u m [ i ] + M x [ i ] ∗ p ) \sigma[i*p] = \sigma[i]/sum[i]*(sum[i]+Mx[i]*p) σ[i∗p]=σ[i]/sum[i]∗(sum[i]+Mx[i]∗p)
s u m [ i ∗ p ] = s u m [ i ] + M x [ i ] ∗ p sum[i*p] = sum[i] + Mx[i]*p sum[i∗p]=sum[i]+Mx[i]∗p
M x [ i ∗ p ] = M x [ i ] ∗ p Mx[i*p] = Mx[i]*p Mx[i∗p]=Mx[i]∗p
(3) i i i不包含最小质因子 p p p : σ [ i ∗ p ] = σ [ i ] ∗ σ [ p ] = σ [ i ] ∗ ( p + 1 ) \sigma[i*p] = \sigma[i]*\sigma[p]= \sigma[i]*(p+1) σ[i∗p]=σ[i]∗σ[p]=σ[i]∗(p+1)
s u m [ i ∗ p ] = p + 1 sum[i*p] = p+1 sum[i∗p]=p+1
M x [ i ∗ p ] = p Mx[i*p] = p Mx[i∗p]=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];
}
}
}