筛法求欧拉函数

欧拉函数的定义

在数论中,对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目.

欧拉函数的重要性质

  1. (m,n)=1(即m与n互质),则\varphi (mn)=\varphi(m)\times \varphi(n)
  2. p为质数,则\varphi(p)=p-1
  3. p为质数,则\varphi(p^{k})=(p-1)\times p^{k-1}

对于性质2,若p为质数,则小于pp-1个数都互质,所以\varphi(p)=p-1

根据性质3,若p为质数,则在1...p...2p...3p...p^{k}中,只有p的倍数与p^{k}不互质,则p^{k}

的欧拉函数就等于总数-p的倍数,我们发现以1...p做为一个周期循环节,每个循环节共有p-1个,则\varphi(p^{k})=\frac{p^{k}}{p}\times(p-1),化简得\varphi(p^{k})=(p-1)\times p^{k-1}

欧拉函数的计算

 根据整数惟一分解定理,n=\prod_{i=1}^{s}p_{i}^{a_{i}}=p_{1}^{a_{1}}p_{2}^{a_{2}}...p_{s}^{a_{s}}

\small \varphi(n)=\prod_{i=1}^{s}\varphi(p_{i}^{a_{i}})=\prod_{i=1}^{s}p_{i}^{a_{i}-1}(p-1)=\prod_{i=1}^{s}p_{i}^{a_{i}}(1-\frac{1}{p_{i}})=\prod_{i=1}^{s}p_{i}^{a_{i}}\prod_{i=1}^{s}(1-\frac{1}{p_{i}})=n\times\prod_{i=1}^{s}(1-\frac{1}{p_{i}})=n\times \frac{p_{1}-1}{p_{1}}\times \frac{p_{2}-1}{p_{2}}\times...\times\frac{p_{s}-1}{p_{s}}

所以欧拉函数仅由n和质因子决定,与次数无关。

根据公式我们有试除法求欧拉函数:

int phi(int n) {
  int res = n;
  for(int i = 2; i <= n / i; i++){
    if(n % i == 0){
      res = res / i * (i - 1);
      while(n % i == 0) n /= i;
    }
  }
  if(n > 1) res = res / n * (n - 1);
  return res;
}

最后回归主题,筛法求欧拉函数,通过线性筛在线性的时间内求出1-n每个数的欧拉函数。

根据上文,当i是质数,\small phi[i]=i-1

在线性筛中,每个合数都是被最小质因子筛掉的,那么设有\small p_{j}\small m的最小质因子,则\small m是通过\small p_{j}\times i筛掉的

  1. \small i能被\small p_{j}整除,则i包含了m所有的质因子\small \varphi(m)=m\times \prod_{k=1}^{s}\frac{p^{k}-1}{p_{k}}=p_{j}\times i\times \frac{p^{k}-1}{p_{k}}=p_{j}\times\varphi(i)
  2. \small i不能被\small p_{j}整除,则\small i\small p_{j}是互质的\small \varphi(m)=\varphi(p_{j}\times i)=\varphi(p_{j})\times\varphi(i)=(p_{j}-1)\times\varphi(i)

由上则代码如下,时间复杂度O(n)

const int N = 1e6 + 9;
int p[N], phi[N], cnt;
bool vis[N];
 
void get_phi(int n) {
  phi[1] = 1;
  for(int i = 2; i <= n; i++) {
    if(!vis[i]) {
      p[cnt++] = i;
      phi[i] = i - 1;
    }
    for(int j = 0; p[j] <= n / i ; j++) {
      int m = i * p[j];
      vis[m] = 1;
      if(i % p[j] == 0) {
        phi[m] = p[j] * phi[i];
        break;
      } else {
        phi[m] = (p[j] - 1) * phi[i];
      }
    }
  }
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值