求欧拉函数值 && 打表O(n)

在数论,对正整数n,欧拉函数是1~n的数中与n互质的数的数目,我们记为 φ ( n ) φ(n) ,(后面欧拉定理中会用到)。此函数以其首名研究者欧拉命名。例如 φ ( 8 ) = 4 φ(8)=4 ,因为1,3,5,7均和8互质。

φ ( n ) φ(n) 求解公式:
现假设 n n r r 个质因子p1、p2、p3、、、pr,则:

215-08-04/55c058b16129e

φ ( n ) = n i = 1 r ( 1 1 p   i   ) φ(n)=n\prod_{i=1}^r (1-\frac{1}{p~i~})

欧拉函数的两个性质:来自欧拉函数及其证明(这两个性质可以推出上面的公式)

  • 欧拉函数既然是积性函数,就说明如果n可以分解成两个互质的整数之积, n = p 1 × p 2 n = p1 × p2 ,则
    φ ( n ) = φ ( p 1 p 2 ) = φ ( p 1 ) φ ( p 2 ) φ(n) = φ(p1p2) = φ(p1)φ(p2)
  • 如果n是质数的某一个次方,即n = pk (p为质数,k为大于等于1的整数),则
    φ ( n ) = p k p k 1 = p k 1 ( p 1 ) φ(n) =p^k- p^ {k-1}=p^{k-1}*(p-1)

1、单独求某个欧拉函数值代码: O ( n ) O(\sqrt{n})

int fn(int x)
{
    int ans=x;
    for(int i=2; i<=sqrt(x); i++)
    {
        if(x%i==0)
        {
            ans-=ans/i;
            while(x%i==0)
                x/=i;
        }
    }
    if(x>1)
        ans-=ans/x;
    return ans;
}

2、既然跟n的所有质因子有关,那么就可以利用之前筛素数的知识:埃氏筛法和欧拉筛

      \implies 质数打表———埃氏筛&&欧拉筛

2.1 求1~n的欧拉函数值: O ( n l o g l o g n ) O(nloglogn)
//埃氏筛法中每个合数会被它的每个质因子筛一遍,就完美地求出欧拉函数值了

bool vis[manx];
void make_prime(int n)
{
     memset(vis,0,sizeof(vis));
     vis[0]=vis[1]=1;
     for(int i=1;i<=n;i++)
          ans[i]=i;
     for(int i=2;i<=n;i++)
     {
          if(!vis[i])
          {
               for(int j=i;j<=n;j+=i)
               {
                    vis[j]=1;
                    ans[j]=ans[j]*(i-1)/i;//主角在这里
               }
          }
     }
}

2.2 求1~n的欧拉函数值: O ( n ) O(n)
原理:以下证明来自欧拉线性筛(筛质数,求欧拉函数)

那么,为了求可以在可以在线性时间内求出来所有的欧拉函数,需要事先知道三个性质:
对于一个质数 p p :
性质1: φ ( p ) = p 1 φ( p)=p-1 ;
因为p为质数,而从1到 p p ,只有 p p p p 自本身不互质,其余的 ( p 1 ) (p-1) 个数字都与 p p 互质,因此得出性质1;
性质2:对于 i i % p = = 0 , φ ( i p ) = p φ ( i ) p==0 , φ(i * p)=p * φ(i) ;
性质3:对于 i i % p ! = 0 p ! = 0 , φ ( i p ) = φ ( i ) ( p 1 ) ; φ (i * p) = φ(i) * (p-1);
利用了欧拉函数的积性。而又通过性质1可知, p 1 = φ ( p ) p-1=φ( p) ,因此 φ ( i p ) = φ ( i ) ( p 1 ) = φ ( i ) φ ( p ) φ(i*p)=φ(i)(p-1)=φ(i)*φ ( p) ;
这个,本人才疏学浅,看了各种证明,但还是不明白性质2,性质3是怎么得出来的,所以先当作结论记住吧。
知道了这三个结论之后,在配合欧拉筛筛质数,就可以得出范围内所有的数字的欧拉函数。

代码:

void make_prime(int n)
{
    int cou=0,ans[manx];
    memset(prime,0,sizeof(prime));
    memset(vis,0,sizeof(vis));
    vis[0]=vis[1]=1;
    for(int i=2; i<=n; i++)
    {
        if(!vis[i])
        {
            prime[cou++]=i;
            ans[i]=i-1;//改动部分1(对应性质1)
        }
        for(int j=0; j<cou; j++)
        {
            if(i*prime[j]>n)
                break;
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)
            {
                ans[i*prime[j]]=ans[i]*prime[j];//改动部分2(对应性质2)
                break;
            }
            else
                ans[i*prime[j]]=ans[i]*ans[prime[j]];//改动部分3(对应性质3)
                //或者写成ans[i*prime[j]]=ans[i]*(prime[j]-1);
        }
    }
}

例题:Farey Sequence
感想:质因子是个神奇的存在

发布了52 篇原创文章 · 获赞 26 · 访问量 3187

猜你喜欢

转载自blog.csdn.net/qq_43803508/article/details/96434436