积性函数的性质及证明 + 线性筛
来源:互联网 发布:淘宝食品备案流程图 编辑:程序博客网 时间:2024/04/30 05:26
引言
在数论问题中,积性函数有着广泛的应用。
如在莫比乌斯反演问题中,函数变换之后如何快速维护前缀和往往是最重要也是最难的一步。如果维护的函数具有积性,那就可以尝试利用线性筛在
本文的大部分相关性质及公式来自:
博主将试着证明其中的性质公式,严谨性可能欠缺,其目的主要是帮助记忆和理解。
因水平有限 若有错误之处还望指出qwq~
积性函数的定义和性质
定义: 对于一个定义域为
若对于任意整数
性质:
(1)对于任意积性函数
证明:因
因
证毕。
(2)对于一个大于
若
证明:由积性和完全积性的定义易得。
欧拉函数φ
定义:对于正整数
定义式:若
性质:
(1)欧拉函数为积性函数,而不是完全积性函数。
证明:设两个互质的正整数
则:
因
故推出:
积性函数性质得证。
而完全积性由上证明可见,
(2)假设存在一个素数
证明:
可以从反面来思考这件事,在小于
故由定义:
证毕。
另外还可以从定义式出发去理解这个结论。
(3)欧拉定理:若有互质的两个正整数
此定理常用来求解逆元。
证明:(可参考百度百科)
(4)假设存在一个正整数n,则:
证明:
先考虑特殊情况:
对于一般情况,
当n只含一个质因子时,即
有:
显然,将求和式展开,会有一些项可以合并。
比如
可见:
当
利用积性函数的性质有
同上易得:
证毕。
(5)当
证明:在数论求
由第一个公式,知:
若
这样就能将保证当
故
当
证毕。
例题: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;}
莫比乌斯函数μ
定义式:
性质:
(1)对于任意正整数n,有:
该性质在莫比乌斯反演中有着极大应用。
证明:
当
当
考虑莫比乌斯函数取值的特殊性,若函数值不为
故
由二项式定理,原式等于:
综上所述:
当
当
证毕。
(2)对于任意正整数
证明:
令
由欧拉函数的性质
又由莫比乌斯反演:
推出:
等式两边同除以n,得:
证毕。
线性筛求积性函数
欧拉函数φ
考虑将所有数分成三类:
(1)质数
(2)最小质因子指数为1:
(3)最小质因子指数大于1:
代码:
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)
(2)
(3)
代码:
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
仍然分三类讨论,此时我们还需要维护每一个数
(1)
(2)
(3)
代码:
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; } }}
约数和函数σ
假设一个正整数
则
假设最小质因子为
故我们可以维护两个量:
然后又可以把所有数分成三类:
(1)
(2)
(3)
代码:
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]; } }}
- 积性函数的性质及证明 + 线性筛
- 二叉树的基本性质及证明
- 二叉树的性质及相关证明
- 傅里叶变换(CTFT)的性质及证明
- 证明母函数的一个性质
- MST性质的证明
- MST性质的证明
- 关于一个欧拉函数的性质的证明
- 二叉树的五大性质及证明
- 离散傅里叶变换(DTFT)的性质及证明
- 欧拉函数的一个性质及其证明
- 欧拉函数的性质证明(欧拉筛)
- 【100】深度学习读书笔记:P44函数性质的证明
- 凸优化性质的证明
- 组合数的性质&证明
- 欧拉函数的性质及应用
- 函数极限的概念及性质
- 函数极限的概念及性质
- js对象的深拷贝和浅拷贝
- 下载spring网站的相关文档pdf版本
- 基于docker的GPU测试方法
- 编程思想——第二章
- QT笔记(1)——信号&槽机制,事件
- 积性函数的性质及证明 + 线性筛
- MySql卸载重新安装出现Start service没有响应的解决办法(64位)
- struts2学习笔记 -- day03 struts2整合hibernate环境搭建
- 前端的一些插件和框架的CDN引用
- 【react】关于react框架使用的一些细节要点的思考
- Hibernate SessionFactory
- 【Polya】 hdu 3923(SummerIII Y)
- mongodb安装说明及mongoVUE使用
- Container With Most Water