前面就不写分析了,所有的注释均在相应代码附近
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long ll;
const int Size = 2333333;
int n;
int prime[Size],phi[Size],factor_max[Size];
// prime[0] 目前质数的总个数,prime[i] 第i个质数的值
// phi[i] i的欧拉函数值 欧拉函数:比i小且与i互质的数的个数
// factor_max[i] i的最大质因子,即i由factor_max[i]筛出
void Euler(void);//通过欧拉筛法求出1~n的phi值,以及筛查1~n中的素数
int main(){
scanf("%d",&n);
Euler();
// 输出1~n中的素数
for (int i = 1;i <= prime[0]; ++i)
printf("%d ",prime[i]);
puts("");
//输出1~n中各数的欧拉函数值
for (int i = 1;i <= n; ++i)
printf("%d ",phi[i]);
puts("");
return 0;
}
void Euler(void){
for (int i = 2;i <= n; ++i){
//i还没有被之前的数筛出,那么i一定是质数
if (factor_max[i] == 0){
factor_max[i] = i;//质数的最大的质因子是自己
prime[++prime[0]] = i;// 添加新的质数
phi[i] = i-1; // 欧拉函数的性质,质数的phi为本身的值-1 想想就是这样
}
for (int j = 1;j <= prime[0]; ++j){
if (prime[j] * i > n) break;// 超出所求范围,不必再求
if (i % prime[j] != 0)//prime[j]不是i的因子
phi[i * prime[j]] = phi[i] * (prime[j] - 1);//phi为积性函数,拥有其性质
else phi[i * prime[j]] = phi[i] * prime[j];// 理同上,此时prime[j]是i的因子
factor_max[i * prime[j]] = prime[j];// 筛出可求出的最小的合数,此处的最小很重要
if (i % prime[j] == 0) break;
}
}
phi[1] = 1;//1 的phi指要自己输入,无法筛出,毕竟前面已经没有其他的数字了
}
浙公网安备 33010602011771号