定义:欧拉函数是小于n的数中与n互质的数的数目。例如φ(8)=4,因为1,3,5,7均和8互质。

欧拉函数的通式为$φ(x)=x (1-\left(\frac{1}{p1}\right))(1-\left(\frac{1}{p2}\right))…(1-\left(\frac{1}{pk}\right))$:,其中pi表示x的质因数。

特别声明,φ(1)=1。

注意:每种质因数只一个。比如$12=223$那么$φ(12)=12(1-\left(\frac{1}{2}\right))(1-\left(\frac{1}{3}\right))=4$

其中还有比较特殊的几个。

  1. 若p为质数,$n=p^k$ ,则$φ(n)=p^k-p^k-1$ 。
  2. 如果n是奇数,那么$φ(2n)=φ(n)$
  3. 如果n是质数,那么,$φ(n)=n-1$ ,即所有小于n的数都与他互质。
  4. $φ(ab)=φ(a)φ(b)$
  5. 如果i%p==0,那么,$φ(ip)=φ(i)p$;

计算时$phi(x)=x(1-\left(\frac{1}{p1}\right))…(1-\left(\frac{1}{pi}\right))$中的x(1-1/pi)可以转化为x/pi*(pi-1)用来避免小数的产生,同时先除后乘可以避免溢出。

单个欧拉函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void euler(int n)
{
for (int i=1;i<=n;i++) phi[i]=i;
for (int i=2;i<=n;i++)
{
if (phi[i]==i)//这代表i是质数
{
for (int j=i;j<=n;j+=i)
{
phi[j]=phi[j]/i*(i-1);//把i的倍数更新掉
}
}
}
}

线性筛

思想:保证每个合数只会被他的最小之质因子筛去。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void euler(int n)
{
phi[1]=1;//1要特判
for (int i=2;i<=n;i++)
{
if (flag[i]==0)//这代表i是质数
{
prime[++num]=i;
phi[i]=i-1;
}
for (int j=1;j<=num&&prime[j]*i<=n;j++)//经典的欧拉筛写法
{
flag[i*prime[j]]=1;//先把这个合数标记掉
if (i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];//若prime[j]是i的质因子,则根据计算公式,i已经包括i*prime[j]的所有质因子
break;//经典欧拉筛的核心语句,这样能保证每个数只会被自己最小的因子筛掉一次
}
else phi[i*prime[j]]=phi[i]*phi[prime[j]];//利用了欧拉函数是个积性函数的性质
}
}
}

评论




博客内容遵循 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议

载入天数...载入时分秒... 本站使用 Volantis 作为主题 鲁ICP备-20012065号