代码思想来自埃拉托斯特尼筛法,参考:http://blog.csdn.net/synapse7/article/details/18727405
简要地解释下phi(k*p^2) = p*phi(kp):(请把k素数分解之后思考)
因为phi(p^r)=p^r-p^(r-1),phi(p^(r-1))=p^(r-1)-p^(r-2),所以phi(p^r)=p*phi(p^(r-1))
#include <cstdio>
const int mx = 50001;
int prime[mx], phi[mx];
bool unprime[mx];
///O(NloglogN),推荐
void phi_table()
{
int i, j;
for (i = 2; i < mx; ++i)
if (!phi[i])
for (j = i; j < mx; j += i)
{
if (!phi[j]) phi[j] = j;
phi[j] -= phi[j] / i; ///简化后的代码
}
}
///O(N)
void linear_phi_table2()
{
int i, j, k = 0;
for (i = 2; i < mx; i++)
{
if (!unprime[i]) ///若i为素数,phi(i)=i-1
{
prime[k++] = i;
phi[i] = i - 1;
}
for (j = 0; j < k && prime[j] * i < maxn; j++)
{
unprime[prime[j] * i] = true;
if (i % prime[j]) ///若i和p互素,则phi(i*p) = phi(i) * phi(p) = phi(i) * (p-1)
phi[prime[j] * i] = phi[i] * (prime[j] - 1);
else
{
///此时有i=kp,则
///phi(p*kp) = phi(k*p^2) = p*phi(kp)
phi[prime[j] * i] = phi[i] * prime[j];
break;
}
}
}
}
int main()
{
phi_table();
return 0;
}