欧拉函数定义:
简单推理:
当 p p p是质数时,显然有 φ ( p ) = p − 1 φ(p) = p - 1 φ(p)=p−1。
当
p
p
p,
q
q
q为质数时,有
φ
(
p
q
)
=
(
p
−
1
)
(
q
−
1
)
=
p
q
(
1
−
1
p
)
(
1
−
1
q
)
φ(pq) = (p - 1)(q - 1) = pq(1 - \frac{1}{p})(1-\frac{1}{q})
φ(pq)=(p−1)(q−1)=pq(1−p1)(1−q1)
首先,对于
1
1
1 ~
p
q
pq
pq 这
p
q
pq
pq个数,我们考虑有多少个数与
p
q
pq
pq是不互质的。
有,
p
,
2
p
,
3
p
,
.
.
.
,
(
q
−
1
)
p
p, 2p, 3p, ..., (q-1)p
p,2p,3p,...,(q−1)p共
q
−
1
q-1
q−1个 和
q
,
2
q
,
3
q
,
.
.
.
,
(
p
−
1
)
q
q,2q,3q,...,(p-1)q
q,2q,3q,...,(p−1)q共p-1个,最后在加上
p
q
pq
pq这一个。
所以,与
p
q
pq
pq互质的数有
p
q
−
(
p
−
1
)
−
(
q
−
1
)
−
1
pq - (p-1)-(q-1)-1
pq−(p−1)−(q−1)−1个。
p
q
−
(
p
−
1
)
−
(
q
−
1
)
−
1
=
p
q
−
p
−
q
+
1
=
(
p
−
1
)
(
q
−
1
)
pq - (p-1)-(q-1)-1=pq-p-q+1=(p-1)(q-1)
pq−(p−1)−(q−1)−1=pq−p−q+1=(p−1)(q−1)。
对于
p
k
p^k
pk,其中
p
p
p是质数,有
φ
(
p
k
)
=
p
k
−
p
k
−
1
=
p
k
∗
(
1
−
1
p
)
\varphi(p^k)=p^k-p^{k-1}=p^k*(1-\frac{1}{p})
φ(pk)=pk−pk−1=pk∗(1−p1)
同样的,我们只考虑在这
p
k
p^k
pk个数中有多少个是与
p
k
p^k
pk不互质的。
有
p
,
2
p
,
3
p
,
.
.
.
,
p
k
−
1
p
p,2p,3p,...,p^{k-1}p
p,2p,3p,...,pk−1p共
p
k
−
1
p^{k-1}
pk−1个。
所以,与
p
k
p^k
pk互质的数有
p
k
−
p
k
−
1
p^k-p^{k-1}
pk−pk−1个。
同时,欧拉函数还有一个性质
欧拉函数是积性函数,但不是完全积性函数。
当且只当
n
n
n可以分解成两个互质的整数之积,
n
=
p
1
×
p
2
n = p_1 × p_2
n=p1×p2,则
φ
(
n
)
=
φ
(
p
1
p
2
)
=
φ
(
p
1
)
φ
(
p
2
)
φ(n) = φ(p_1p_2) = φ(p_1)φ(p_2)
φ(n)=φ(p1p2)=φ(p1)φ(p2)
有了以上的知识,我们就可以快速的利用公式计算任意一个正整数 n n n的欧拉函数。
由算术基本定理可以知道,任意一个正整数
x
x
x都可以唯一的分解成若干个质数的乘积。
即
x
=
p
1
k
1
∗
p
2
k
2
∗
p
3
k
3
∗
.
.
.
∗
p
n
k
n
x = p_1^{k_1}*p_2^{k_2}*p_3^{k_3}*...*p_n^{k_n}
x=p1k1∗p2k2∗p3k3∗...∗pnkn
所以,
φ
(
x
)
=
φ
(
p
1
k
1
)
∗
φ
(
p
2
k
2
)
∗
φ
(
p
3
k
3
)
∗
.
.
.
∗
φ
(
p
n
k
n
)
=
p
1
k
1
∗
(
1
−
1
p
1
)
∗
.
.
.
∗
p
n
k
n
∗
(
1
−
1
p
n
)
=
x
∗
(
1
−
1
p
1
)
∗
(
1
−
1
p
2
)
.
.
.
∗
(
1
−
1
p
n
)
\varphi(x)=\varphi(p_1^{k_1})*\varphi(p_2^{k_2})*\varphi(p_3^{k_3})*...*\varphi(p_n^{k_n}) \\=p_1^{k_1}*(1-\frac{1}{p_1})*...*p_n^{k_n}*(1-\frac{1}{p_n}) \\=x*(1-\frac{1}{p_1})*(1-\frac{1}{p_2})...*(1-\frac{1}{p_n})
φ(x)=φ(p1k1)∗φ(p2k2)∗φ(p3k3)∗...∗φ(pnkn)=p1k1∗(1−p11)∗...∗pnkn∗(1−pn1)=x∗(1−p11)∗(1−p21)...∗(1−pn1)
单个欧拉函数求法:
int euler(int x)
{
int res = x;
for(int i = 2; i <= x / i; i ++)
if(x % i == 0)
{
res = res / i * (i - 1);
while(x % i == 0) x /= i;
}
if(x > 1) res = res / x * (x - 1);
return res;
}
区间欧拉函数筛法:
(求1~n的欧拉函数值)
1、埃氏筛思想:
const int maxn=1e6+5;
int phi[maxn]; //phi[i]是i的欧拉函数值
void Euler(int n)
{
//首先将每个数的欧拉函数值都初始化为它自己
for(int i=1;i<=n;i++) phi[i]=i;
for(int i=2;i<=n;i++)
{
//对于每一个质数p,对2p,3p,...的欧拉函数值/p*(p-1)
if(phi[i]==i)
{
for(int j=i;j<=n;j+=i)
phi[j]=phi[j]/i*(i-1);
}
}
}
int main()
{
int n; cin>>n;
Euler(n);
return 0;
}
2、线性筛过程中求欧拉函数:
const int N = 1e6+5;
int prime[N],cnt,phi[N];
bool vis[N];
void get_euler(int n)
{
phi[1]=1;
for(int i=2;i<=n;i++)
{
if(!vis[i])
{
prime[cnt++]=i;
phi[i]=i-1;
}
for(int j=0;prime[j]<=n/i;j++)
{
vis[prime[j]*i]=1;
if(i%prime[j]==0)
{
phi[prime[j]*i]=phi[i]*prime[j];
break;
}
phi[prime[j]*i]=phi[i]*(prime[j]-1);
}
}
}
int main()
{
int n; cin>>n;
get_euler(n);
return 0;
}