注意事项:
包含线性筛的运用,可以看我之前的文章:java—朴素/埃式/欧拉—筛质数
题目:
给定一个正整数 n,求 1∼n 中每个数的欧拉函数之和
输入:
6
输出:
12
public class 欧拉函数_欧拉函数之和 {
//count是质数个数,st判断当前数是否为合数,primes存储所有的质数,phi存储1-x中每个数的欧拉函数
public static int N = 10000010, count = 0;
public static int[] primes = new int[N], phi = new int[N];
public static boolean[] st = new boolean[N];
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int x = in.nextInt();
System.out.println(Euler(x));
}
public static long Euler(int x) {
//phi[1]设定为1
phi[1] = 1;
//在欧拉(线性筛)中,进行修改,来求出每个数的欧拉函数
for (int i = 2; i<=x; i++) {
if (!st[i]) { //如果当前数i为质数,那么所有1到(i-1)的数都和n互质,phi[i] = i-1即可
primes[count++] = i;
phi[i] = i-1;
}
for (int j = 0; primes[j] <= x/i; j++) { //这里根据每个数i,找到所有以i为因数的不大于x的合数,并用st进行标记,这也是"线性"的来源
st[primes[j] * i] = true;
if (i % primes[j] == 0) { //当 i % pj == 0时,代表当前质数是i的最小质因子
phi[primes[j] * i] = phi[i] * primes[j];
break;
}
else { //当 i % pj != 0时,代表当前质数不是i的最小质因子
phi[primes[j] * i] = phi[i] * (primes[j]-1);
}
}
}
//对所有1-x的数的欧拉函数求和
long res = 0;
for (int i = 1; i<=x; i++) {
res += phi[i];
}
return res;
}
}
声明:算法思路来源为y总,详细请见https://www.acwing.com/
本文仅用作学习记录和交流