欧拉函数求解(因数分解和线性筛)

C++

欧拉函数及其简略证明

/*
* 欧拉函数
*
* 定义:
* 互质定义:
* 互质是公约数只有1的两个整数,叫做互质整数。公约数只有1的两个自然数,叫做互质自然数。
* 欧拉函数定义:
* 在 1 ~ N 中和 N 互质的数的个数被称为欧拉函数,记作 phi(N)。
*
* 欧拉函数普通解法
* 计算 N 的欧拉函数,使用欧几里得算法查看 1 ~ N 中的数字谁和 N 互质。
*
* 排除法推公式:
* N 质因数分解后可得:
* N = p_1 ^ a_1 * p_2 ^ a_2 * ... * p_k ^ a_k
* 那么利用排除法,1 ~ N 中和 N 互质的数的个数为:
* N - N / p_1 - N / p_2 - ... - N / p_k
* + N / (p_1) ...
* = N * (1 - (1 / p_1) * (1 - (1 / p_2) * ... * (1 - (1 / p_k))
* 同时可以看出,她和我们算数基本定理组成的素数有关,借助素数的递归关系,在线性筛的过程中求解
* 有点向容斥定理那里走
*
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 1000010;
int n;
bool st[N];
int phi[N];
long long seive_get_phi(int n) {
phi[1] = 1;
memset(st, false, sizeof st);
vector<int> primes;
for (int i = 2; i <= n; i ++ ) {
if (st[i] == false) {
primes.push_back(i);
phi[i] = i - 1;
}
for (int j = 0; primes[j] <= n / i; j ++ ) {
st[i * primes[j]] = true;
if (i % primes[j] == 0) { // 注意这里的判断挺有意思
phi[i * primes[j]] = phi[i] * (primes[j]);
break;
} else {
phi[i * primes[j]] = phi[i] * (primes[j] - 1);
}
}
}
long long res = 0;
for (int i = 1; i <= n; i ++ ) {
res += phi[i];
// printf("i=%d, phi=%d\n", i, phi[i]);
}
return res;
}
int get_phi(int x) {
vector<int> primes;
int res = x;
for (int i = 2; i <= x / i; i ++ ) {
if (x % i == 0) {
primes.push_back(i);
while (x % i == 0) {
x /= i;
}
}
}
if (x != 1) {
primes.push_back(x);
}
for (int i = 0; i < primes.size(); i ++ ) {
res = res - res / primes[i]; // res / primes[i] 一定是整数,自己可以证明的
}
return res;
}
int main()
{
scanf("%d", &n);
printf("%lld\n", seive_get_phi(n));
return 0;
}
posted @   lucky_light  阅读(211)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示