C++数学-数论欧拉函数流食般投喂


本编介绍的是欧拉函数,其中欧拉筛打表欧拉函数是本章重点。
欧拉函数:
【互质】
a 与 b 互质:说明 a 与 b 的最大公约数是 1.
【欧拉函数】
对于一个数 n,在 1~n 中,与 n 互质的数的个数,就是欧拉函数,用
表示。比如:
。
【积性函数】
若函数
满足:
。则称其为积性函数。
【欧拉函数的性质】
1、若 p 为质数,则
;
2、若 p 为质数,则
;
3、欧拉函数为积性函数:
。
【试除法求单个数的欧拉函数】
计算公式:
。
推导过程:
由此可知,在求解某一个数的欧拉函数时,我们只需要知道它的质因数就可以求解。
// 试除法求解某一个数的欧拉函数,根据计算公式可得,其只与它的质因数有关,而且是分阶段的 int phi(int n) { int ret = n; for (int i = 2; i <= x / i; i++) { if (n % i == 0) // 找到 i 的质因数 { ret = ret / i * (i - 1); // 先除后乘,这是防溢出的写法 while (n % i == 0) // 通过最小质因数除尽,之后就不会以 i的倍数 当作n的质因数了 { n /= i; } } } // 特判此时如果有大于sqrt(n)的质因数 if (n > 1) ret = ret / n * (n - 1); return ret; }时间复杂度:
枚举到 sqrt(n),因此时间复杂度为 O(sqrt(n))。
【欧拉筛打表欧拉函数】
这其实就是用线性筛打表,在线性筛的过程中算出每个数对应的欧拉函数。
问题背景:需要知道 [1,n] 中,每个数的欧拉函数。
📌在线性筛的过程中:
1、如果是质数,则就用欧拉函数的性质一,i 的欧拉函数就是 i - 1;
2、如果是合数:
现令 x = i * p[j]:
2.1、i % p[j] != 0:就代表 i 和 p[j] 是互质的,就可以用欧拉函数的性质三,x 的欧拉函数就是 (i 的欧拉函数)* (p[j] 的欧拉函数),p[j] 是质数,又可以用欧拉函数的性质一,p[j] - 1,
。
2.2、i % p[j] == 0:就代表 p[j] 是 i 的因数,i 这个数里面包含了 x 所有的质因子,用公式计算,再用 i 和 x 的因子相同,等价交换:
int n; bool st[N]; int p[N], cnt; int phi[N]; // 欧拉函数表 void get_phi() { phi[1] = 1; for (int i = 2; i <= n; i++) { if (!st[i]) { p[++cnt] = i; phi[i] = i - 1; // 性质一 } for (int j = 1; 1ll * i * p[j] <= n; j++) { int x = i * p[j]; st[i * p[j]] = true; if (i % p[j] != 0) { phi[x] = phi[i] * (p[j] - 1); // (主)性质三 + 性质一 } else { phi[x] = p[j] * phi[i]; // 公式法 (正推拆 + 反推合) break; } } } }时间复杂度:
时间复杂度与线性筛一致,O(n)。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐



所有评论(0)