线性(欧拉)筛&欧拉函数

Posted pigzhouyb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线性(欧拉)筛&欧拉函数相关的知识,希望对你有一定的参考价值。

线性筛法

what is 线性筛??就是基于最基本的筛法的优化。
在基础的筛法上,我们发现有的数字会被重复筛,例如6既会被2枚举到也会被3枚举到,必然有重复运算。
我们的做法就是让每一个数的最小因数筛。
(FOR) (EXAMPLE:)
有一个数(2 * 2 * 3 * 5)
有另一个数 (3 * 3 * 3* 5)
那么第一个数枚举到3的话,筛到的数字是(2 * 2 * 3 * 3 * 5)
但是在第二个数字再次枚举的时候 枚举到2时 也会枚举到(2 * 2 * 3 * 3 * 5)
因此,维护这个最小质因数即可。
怎么维护??
(i) (mod) (这个质因数) (=0) 说明是质因数,第一次枚举到就要(break),这样就保证了一定会被最小素因数给筛。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,cnt=0;
    int prime[10000]={};//用来存储素数 
    int Vis[10000]={};//用来判断是否是素数
    cin>>n;
    for (int i=2;i<=n;i++)
    {
        if (Vis[i]==0) prime[++cnt]=i;//如果没有被标记过 
        for (int j=1;j<=cnt&&i*prime[j]<=n;j++)//用i去乘上每一个已经求过的素数 
        {
            Vis[i*prime[j]]=1;//标记素数 
            if (i%prime[j]==0) break;//下面再解释 
        }
    }
    for (int i=2;i<=n;i++) 
        if (Vis[i]==0) cout<<i<<‘ ‘;
    return 0; 
} 

一、欧拉函数概念

欧拉函数,是表示1~n中与n互质的元素的个数,记为(φ(n))

二、性质

  • 如果n为某一素数p,显然(φ(p))为p-1
  • 如果n为某一素数的幂次,那么: [phi(p^a)=(p-1)*p^ {a-1}]
    我们可以来推导次函数的求法
    我们先将n分解质因数得:
    [n=a1^{b1}*a2^{b2}*a3^{b3}*……*ak^{bk}]

因为φ(n)求的是与n互质的数的个数,所以其中不能有n的因数,即不能出现a1,a2,a3……ak的倍数。
那么我们来转换思路,n个数之中存在多少个a1的倍数,多少个a2的倍数……多少个ak的倍数呢?
显然有n/a1个a1的倍数,n/a2个a2的倍数……有n/ak个ak的倍数。

所以(φ(n)=n-frac{1}{a1} -frac{1}{a2}-frac{1}{a3}-……-frac{1}{ak})
将n提取出来得到:
[φ(n)=n*(1-frac{1}{a1})*(1-frac{1}{a2})*(1-frac{1}{a3})*……*(1-frac{1}{ak})]

于是欧拉函数的公式就这么推导出来了

还有如下性质:

  • 如果i mod p=0,那么(φ(i*p)=p*φ(i))
    证明:
    对于公式[φ(1)=n*(1-frac{1}{a1})*(1-frac{1}{a2})*(1-frac{1}{a3})*……*(1-frac{1}{ak})]
    得到
    [φ(n)=n*p*(1-frac{1}{a1})*(1-frac{1}{a2})*(1-frac{1}{a3})*……*(1-frac{1}{ak})]
    因为p已经是i的因数,后半部分不需要添加
    因此得证。
  • 函数的积性,(φ(i*j)=φ(i)*φ(j))

  • 如果i mod p≠0,那么(φ(i*p)=φ(i)*(p-1))
    根据
    [φ(n)=n*(1-frac{1}{a1})*(1-frac{1}{a2})*(1-frac{1}{a3})*……*(1-frac{1}{ak})]
    得到
    [φ(n)=n*p*(1-frac{1}{a1})*(1-frac{1}{a2})*(1-frac{1}{a3})*……*(1-frac{1}{ak})*(1-frac{1}{p})]
    因为p不是i的因数,因此最后要加上((1-frac{n}{ak}))部分。
    证明完成。

三、求法

下面给两种求法。

(1).公式法

根据公式(φ(n)=n*(1-frac{1}{a1})*(1-frac{1}{a2})*(1-frac{1}{a3})*……*(1-frac{1}{ak})*(1-frac{1}{p}))

inline LL eular(LL x)
{
    LL sum=x,y=x;
    for (LL i=2;i*i<=y;++i)
    {
        if (x%i!=0) continue;
        sum=sum/i*(i-1); 
        while (x%i==0) x/=i;
    }
    if (x>=2) sum=sum/x*(x-1);
    return sum;
}
//公式求x欧拉函数 

(2).线性筛求欧拉函数

根据三条性质推导即可。
线性筛中每一个数字最多只会被筛一次,因此正好可以对每一个数字求欧拉函数。
线性筛正好是由小的数字筛到大的数字 or 正好是指数
前者用后两条性质 后者用第一条性质即可。
三条性质如下:

  • 如果n为某一素数的幂次,那么: (phi(p^a)=(p-1)*p^ {a-1})
  • 如果i mod p=0,那么(φ(i*p)=p*φ(i))
  • 如果i mod p≠0,那么(φ(i*p)=φ(i)*(p-1))
inline void findphi(void)
{
    phi[1]=1,prm[1]=0;
    for (LL i=2;i<=n;++i)
    {
        if (!v[i]) { prm[++cnt]=i, phi[i]=i-1; }
        for (LL j=1;j<=cnt && i*prm[j]<=n;++j)
        {
            v[i*prm[j]]=1;
            if (i%prm[j]==0) { phi[i*prm[j]]=phi[i]*prm[j]; break; }
            if (i%prm[j]!=0) phi[i*prm[j]]=phi[i]*(prm[j]-1);   
        }   
    }
    return; 
} 

后记

部分参考hkh大佬的博客。
在此表示感谢!
如有纰漏请读者指正!
<font>





































以上是关于线性(欧拉)筛&欧拉函数的主要内容,如果未能解决你的问题,请参考以下文章

欧拉函数线性筛法

欧拉筛素数+求欧拉函数

欧拉筛线性处理莫比乌斯函数

线性求欧拉函数

欧拉线性筛模板

The Euler function(线性筛欧拉函数)