数论
常见数论函数
欧拉函数
单位函数
恒等函数
常数函数
除数函数
莫比乌斯函数
数论中的加性函数指:对于一个数论函数
卷积
对于两个数论函数
记为
狄利克雷卷积运算满足交换律、结合律与加法结合律(即
等式的性质:
狄利克雷卷积单位元
数论函数的逆元:若两数论函数
性质
对于两积性数论函数
常见卷积
此类卷积会在后面的莫比乌斯反演中大量运用。
前缀和
对于一个数列
若要求一个数列的
void Linear_Sieve() { for (int i = 2; i <= n; i++) { if (!vis[i]) { prime[++tot] = i; } for (int j = 1; j <= tot && i * prime[j] <= n; j++) { vis[i * prime[j]] = 1; if (i % prime[j] == 0) break; } } for (int i = 1; i <= tot; i++) { for (int j = 1; prime[i] * j <= n; j++) { a[prime[i] * j] += a[j]; } } }
反演
若两数论函数
则称
这里容易看出,
求
考虑对式子作下列变换:
第一行,枚举
第二行,将
第三行,观察到
第四行,再次枚举
第五行,改变枚举顺序。
第六行,观察到
//上面的过程好像有问题,懒得改了。
最后,线性筛出
本题还有不用反演的做法:利用
下面是
求
比刚刚那题一目了然,但刚刚用
化简得到:
此时不能再枚举
考虑设
预处理后一部分,整除分块即可,时间复杂度
//Made By Cuset. 喵喵~ #include <bits/stdc++.h> #include <bits/extc++.h> using namespace std; using namespace __gnu_pbds; typedef long long ll; typedef long double ld; typedef unsigned long long ull; typedef pair<int, int> pii; const int MAXN = 1e7 + 5; ll mu[MAXN], prime[MAXN], f[MAXN], tot, fsum[MAXN], n, m, t; bool vis[MAXN]; void Linear_Sieve() { mu[1] = 1; for (int i = 2; i <= MAXN - 5; i++) { if (!vis[i]) { prime[++tot] = i; mu[i] = -1; } for (int j = 1; j <= tot && i * prime[j] <= MAXN - 5; j++) { vis[i * prime[j]] = 1; if (i % prime[j] == 0) break; else mu[i * prime[j]] = -mu[i]; } } for (int i = 1; i <= tot; i++) { for (int j = 1; j * prime[i] <= MAXN - 5; j++) { f[j * prime[i]] += mu[j]; } } for (int i = 1; i <= MAXN - 5; i++) fsum[i] = fsum[i - 1] + f[i]; } inline ll read() { ll x = 0; bool f = true; char c = getchar(); while (!isdigit(c)) { if (c == '-') f = false; c = getchar(); } while (isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } return f ? x : -x; } inline void write(ll x, bool f = 0) { ll tp2 = 0; char Nu[64]; if (x<0) x = -x, putchar('-'); if (x==0) putchar('0'); else { while (x) { Nu[++tp2] = x % 10 + '0', x /= 10; } while (tp2) putchar(Nu[tp2--]); } if (f) putchar('\n'); else putchar(' '); return; } int main() { Linear_Sieve(); cin >> t; while (t--) { n = read(); m = read(); ll ans = 0; if (n > m) swap(n, m); for (int l = 1, r; l <= n; l = r + 1) { r = min(n / (n / l), m / (m / l)); ans += (fsum[r] - fsum[l - 1]) * (n / l) * (m / l); } write(ans, true); } return 0; }
杜教筛
类比线性筛、埃氏筛能筛质数与积性函数值,杜教筛是一种用于大范围筛数论函数前缀和的工具,它的底层思想是构造卷积与
假设现在需要求
推出杜教筛的核心式子:
理论上,只要找到一个合适的积性函数
代码如下:
ll GetSum(int n) { // 算 f 前缀和的函数 ll ans = ...; // f * g 的前缀和 for(ll l = 2, r; l <= n; l = r + 1) { r = (n / (n / l)); ans -= (g_sum(r) - g_sum(l - 1)) * GetSum(n / l); // g_sum 是 g 的前缀和 // 递归 GetSum 求解 } return ans; }
计算
考虑
计算
考虑
朴素的杜教筛的时间复杂度是 unordered_map
存下来,当
原根与离散对数
阶
满足
若存在
若
设
若
与阶的最小性相矛盾。
若
据此还能推出:若
求阶
由于
试除法的步骤是:
-
设
,其中 表示已除去的所有因子的积。 -
在试除的过程中,若
不成立,则该因子不能除去,否则可以除去。
原根
设
原根判定定理
设
证明见 OI-wiki。
原根个数
若
原根存在性定理
一个数
离散对数
离散对数的定义与对数类似。
设
本文作者:Cuset_VoidAldehyde
本文链接:https://www.cnblogs.com/CusetVoidAldehyde/p/18286073
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步