一、n的欧拉phi函数值
思路:需要用试除法依次判断√n内的素数,这样需要先生成√n内的素数表,但其实不必这么麻烦:只需要每次找到一个素因数之后把它“除尽”,即可保证找到的因数都是素数(假如当前找到的因素不是素数,则存在更小的因数,与“除尽“矛盾)
O(√n)
1 int euler_phi(int n) 2 { 3 int m = (int)sqrt(n + 0.5); 4 int ans = n; 5 for (int i = 2; i <= m; i++) 6 { 7 if (n % i == 0) 8 { 9 ans = ans / i * (i - 1); 10 while (n % i == 0) n /= i; //除尽 11 } 12 } 13 if (n > 1) ans = ans / n * (n - 1); //剩下的不为1,也是素数 14 return ans; 15 }
二、1~n中所有数的欧拉phi函数值
思路:与素数筛法非常类似,先筛得素数,然后乘到phi值上(因为如果含有素数p,那么公式中会包含(1 - 1/p))
O(nloglogn)
时间复杂度与埃氏筛法一样的
1 const int maxn = 100000 + 10; 2 int phi[maxn]; 3 void phi_table(int n, int* phi) 4 { 5 for (int i = 2; i <= n; i++); 6 phi[1] = 1; 7 for (int i = 2; i <= n; i++) 8 { 9 if (!phi[i]) //筛法得到素因数i,此时1~i的phi值已经确定 10 { 11 for (int j = i; j <= n; j += i) 12 { 13 if (!phi[j]) phi[j] = j; 14 phi[j] = phi[j] / i * (i - 1); //更新 15 } 16 } 17 } 18 }