数论-欧拉筛和埃氏筛

1. 埃氏筛

mk[i] = true 表示 i 不是素数。时间复杂度好像(OrzOrz)是 O(√N) 。有的代码可能会写 for (j = i*2; ... ) 其实不用,因为 i*2, i*3 ... i*(i-1) 都在之前的循环里讨论过了,所以 j 从 i*i 开始扫就可以了。但整体而言两种写法时间复杂度是一样的。

1     mk[1] = true;
2     for (i = 2; i <= N; ++i) {
3         if (mk[i]) continue;
4         for (j = i*i; j <= N; j += i) mk[i] = true;
5     }

1. 欧拉筛

时间复杂度是 O(N) ,因为每个数只会被它最小的素约数筛到。

 1 void euler(int mx)
 2 {
 3     int i, j, cnt = 0;
 4     for (i = 2; i <= mx; ++i) {
 5         if (!mark[i]) P[++cnt] = i, phi[i] = i-1;
 6         for (j = 1; j <= cnt && i*P[j] <= mx; ++j) {
 7             mark[i*P[j]] = true;
 8             if (!(i % P[j])) { phi[i*P[j]] = phi[i] * P[j]; break; }
 9             phi[i*P[j]] = phi[i] * (P[j]-1);
10         }
11     }
12     return;
13 }

2. 单个 phi 值计算

 1 int phi(int v)
 2 {
 3     if (v == 1) return 1;
 4     int ans = v, i;
 5     for (i = 2; i*i <= v; ++i) {
 6         if (v % i) continue;
 7         ans -= ans / i;
 8         while (!(v % i)) v /= i;
 9     }
10     if (v > 1) ans -= ans / v;
11     return ans;
12 }
原文地址:https://www.cnblogs.com/ghcred/p/8455285.html