一个数与
设
于是有
设
又设
对
设
于是得
若正整数
对
根据
int phi(int n) {
int ans = n;
for (int i = 2; i * i <= n; i++) {
int cnt = 0;
while (n % i == 0) {
n /= i;
cnt++;
}
if (cnt)
ans -= ans / i;
}
if (n > 1)
ans -= ans / n;
return ans;
}
设正整数
根据这个性质,我们可以利用素数筛法计算
vector<int> phi_table(int n) {
vector<int> phi(n + 1);
phi[1] = 1;
vector<bool> vis(n + 1);
for (int i = 2; i <= n; i++)
if (!vis[i]) // i是素数
for (int j = 1; j * i <= n; j++)
if (!vis[j * i]) {
phi[j * i] = phi[j] * (j % i ? i - 1 : i);
vis[j * i] = true;
}
return phi;
}
精简写法:
vector<int> phi_table(int n) {
vector<int> phi(n + 1);
phi[1] = 1;
for (int i = 2; i <= n; i++)
if (phi[i] == 0) // i是素数
for (int j = 1; j * i <= n; j++)
if (phi[j * i] == 0)
phi[j * i] = phi[j] * (j % i ? i - 1 : i);
return phi;
}
vector<int> phi_table(int n) {
vector<int> phi(n + 1);
phi[1] = 1;
vector<int> primes;
for (int i = 2; i <= n; i++) {
if (phi[i] == 0) { // i是素数
primes.push_back(i);
}
for (int p : primes) {
if (p * i > n)
break;
if (i % p == 0) {
phi[p * i] = p * phi[i];
break;
} else {
phi[p * i] = (p - 1) * phi[i];
}
}
}
return phi;
}
设
当