数论函数小记
摘自 command_block 大佬的笔记
基础:
-
积性函数:若当
有 ,则称 为积性函数。 -
完全积性函数:若当
, 则称 为完全积性函数。 -
: 值恒为 1 的函数。 -
: 当 时值为 1,否则为 0 。 -
: 。 -
tips:这些都为完全积性函数。
狄利克雷卷积:
给定两个数论函数
特殊的, 我们一个函数
莫比乌斯函数:
-
引理 1:
若两个函数
的卷积为积性函数,且 为积性函数,则 也是积性函数。
我们定义
显然
- tips: 观察一个积性函数,可以先从
的情形入手。
由卷积的定义得:
即为:
又因为
则可以得到
当
否则
一些常见的结论:
-
卷积式:
即 ( 是一个数的约数个数) 则 (重要!!) -
函数运算:
莫比乌斯反演:
十分灵活,主要基于上面的柿子和一些奇怪结论。
看一道例题 P2257 YY的GCD:
题目就是让你求:
(看起来很废话,但是也是重要的)
令
代入
把
整理一下:
- tips: 遇到乘积式需要考虑代换掉并变为整除形式。
还是不好做,发现
- tips: 发现求和式性质不明显时,可以考虑交换枚举变量或交换求和式顺序。
注意到这个柿子只有
令
接着使用整除分块技巧计算前面的柿子即可。
code:
#include<bits/stdc++.h> #define int long long using namespace std; const int N = 1e7 + 10; int prime[N], tot, mu[N], g[N]; bool isprime[N]; void init(){ for(int i = 2; i < N; i++) isprime[i] = true; isprime[1] = false, mu[1] = 1; for(int i = 2; i < N; i++){ if(isprime[i]) prime[++tot] = i, mu[i] = -1; for(int j = 1; j <= tot && i * prime[j] < N; j++){ isprime[i * prime[j]] = false; if(i % prime[j] == 0) break; mu[i * prime[j]] = -mu[i]; } } for(int i = 1; i <= tot; i++){ for(int j = prime[i]; j < N; j += prime[i]){ g[j] += mu[j / prime[i]]; } } for(int i = 2; i < N; i++) g[i] += g[i - 1]; } int H(int n, int m){ int ret = 0, l = 1, r, siz = min(n, m); while(l <= siz){ r = min(siz, min(n / (n / l), m / (m / l))); ret += (g[r] - g[l - 1]) * (n / l) * (m / l); l = r + 1; } return ret; } signed main(){ ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); init(); int T; cin >> T; while(T--){ int n, m; cin >> n >> m; cout << H(n, m) << "\n"; } return 0; }
还有另一种反演形式:
向上面一样的推法可以得出这个柿子等于:
若
杜教筛:
杜教筛是一种高效计算一类数论函数前缀和的筛法。
杜教筛的核心是构造两个合适的数论函数,使得
杜教筛公式:
我们令
于是有:
做一个小小的变换得到:
进行化简:
整理后有:
将
这就是杜教筛公式了。
实现:
首先我们算出
对于一个
可以证明时间复杂度为
例题
本文作者:Little_corn
本文链接:https://www.cnblogs.com/little-corn/p/18157526
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步