目的

求1~N中每个数的欧拉函数

原理

利用线性筛分解质因数的方法

euler[1] = 1;
遍历2 ~ N

  • i为质数 euler[i] = i - 1
  • i % pj == 0φ(i * pj) = i * pj * (1 - 1/p1)(1 - 1/p2)...(1 - 1/pk) = pj * ``φ(i)

φ(i) = i * (1 - 1/p1)(1 - 1/p2)...(1 - 1/pk) = pj * ``φ(i)

  • i % pj != 0φ(i * pj) = i * pj * (1 - 1/p1)(1 - 1/p2)...(1 - 1/pk) * (1 - 1/pj) = pj * φ(i) * (1 - 1/pj) = (pj - 1) * φ(i)

例题

874. 筛法求欧拉函数

给定一个正整数 n,求 1∼n 中每个数的欧拉函数之和。
输入格式
共一行,包含一个整数 n。
输出格式
共一行,包含一个整数,表示 1∼n 中每个数的欧拉函数之和。
数据范围
1≤n≤106
输入样例:

  1. 6

输出样例:

  1. 12

时间复杂度:同线性筛法筛质数

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner sc = new Scanner(System.in);
  5. int n = sc.nextInt();
  6. int[] primers = new int[n];
  7. int idx = 0;
  8. boolean[] st = new boolean[n + 1];
  9. int[] euler = new int[n + 1];
  10. euler[1] = 1;
  11. for (int i = 2; i <= n; i++) {
  12. if (!st[i]) {
  13. primers[idx++] = i;
  14. euler[i] = i - 1;
  15. }
  16. for (int j = 0; primers[j] <= n / i; j++) {
  17. st[primers[j] * i] = true;
  18. if (i % primers[j] == 0) {
  19. euler[i * primers[j]] = euler[i] * primers[j];
  20. break;
  21. }
  22. euler[i * primers[j]] = euler[i] * (primers[j] - 1);
  23. }
  24. }
  25. //注意这里用long类型存储,防止溢出
  26. long ans = 0;
  27. for (int i = 1; i <= n; i++) {
  28. ans += euler[i];
  29. }
  30. System.out.println(ans);
  31. }
  32. }