前言
1.定义
欧拉函数φ(n)= 不大于n 且 与n互质 的正整数的个数(包括1)。
用式子表示则为:φ(n)=
∑
i
=
1
n
[
g
c
d
(
i
,
n
)
=
=
1
]
\sum^{n}_{i=1}{[gcd(i,n)==1]}
∑i=1n[gcd(i,n)==1]
比如φ(1)=1,只有1与之互质;
φ(2)=1,也只有1与2互质。
2.与模n的简化剩余系的区别
之前介绍过简化剩余系的概念,此时加上一个限定条件:模n,就把数据都控制在[0,n)的范围内了。
令这个集合为
z
n
z_n
zn,其中包含的元素为小于n且与n互质的值。
前者为不大于,后者为小于
可以看出两者的1区别在于对1的讨论,1的
z
n
z_n
zn为空,但φ(1)=1;
其余大于1的情况下,n都不会与n互质,故两者表示一致。
式子表示为:
If n>1 |
z
n
z_n
zn|=φ(n) ;
else |
z
n
z_n
zn|=0;
一、p为质数的情况
1.φ(p )=p-1
证明
若p为素数,p仅可以唯一分解出1和p两个因子,对于[1,p)中的数来说,唯一分解的结果中不会包含因子p,所以得到结论:质数与小于它的每一个数,都构成互质关系
也就是:φ(p )=p-1
2.φ( p k p^k pk)= p k p^k pk- p k − 1 p^{k-1} pk−1
证明
对
p
k
p^k
pk进行唯一分解,可以得到因子1和p,此时
p
k
p^k
pk必定大于1,所以我们讨论在1到
p
k
p^k
pk-1中的情况。
总共有
p
k
p^k
pk-1个数,其中与
p
k
p^k
pk不互质也就是含有因子p,不妨将这些数枚举一下:
p,2p,3p……(
p
k
−
1
−
1
p^{k-1}-1
pk−1−1)p
不互质的数总共有
p
k
−
1
−
1
p^{k-1}-1
pk−1−1个,那么用总数减去这一部分剩下的就是与
p
k
p^k
pk互质的部分了。
p
k
−
1
−
p^k-1-
pk−1−
(
p
k
−
1
−
1
)
(p^{k-1}-1)
(pk−1−1) =
p
k
−
p^k-
pk−
p
k
−
1
p^{k-1}
pk−1
二、φ( a b ab ab)的讨论
1.a与b互质时,φ( a b ab ab)=φ( a a a)φ( b b b)满足积性函数
1.a,b均为质数时的证明
若为质数,已知φ(p )=p-1,那么φ(
a
a
a) φ(
b
b
b) = (a-1)(b-1);
ab此时大于1,令n=ab,所以φ(
n
n
n)=|
z
n
z_n
zn|
对n进行唯一分解,可得因子1、a和b,所以用集合{1,2…n-1}减去与a,b不互质的数,剩下的元素就都与n互质。
而
z
n
z_n
zn={1,2,3…n-1}
−
-
−{a,2a…(b-1)*a}
−
-
−{b,2b…(a-1)*b}
可以看出后两个集合不会出现重复元素,所以
|
z
n
z_n
zn|=n-1-(b-1)-(a-1)
=ab-1-b+1-a+1
=ab-a-b+1
=(a-1)(b-1)
=φ(
a
a
a)φ(
b
b
b)
即φ( a b ab ab)=φ( a a a)φ( b b b)
2.a,b互质时的证明
3.例题·Euler Function
题目大意是给定一个k值,求出φ(
n
n
n)为合数的情况下第k小的φ(
n
n
n)所对应的n
φ(
1
1
1)=1;
φ(
2
2
2)=1;
φ(
3
3
3)=2;
φ(
4
4
4)=2;
φ(
5
5
5)=4;
φ(
6
6
6)=2;
φ(
7
7
7)=6;
……
当k为1时,φ(
5
5
5)=4,是满足合数的第一个数,所以输出5;
当k为2时,φ(
7
7
7)=6,是满足合数的第二个数,所以输出7;
思路:
讨论一个大于1的数n,n可以被唯一分解,得:
n=
p
1
k
1
p_{1}^{k_1}
p1k1
p
2
k
2
p_{2}^{k_2}
p2k2…
p
m
k
m
p_{m}^{k_m}
pmkm
这几个质因数之间满足互质条件,所以可得:
φ(n) = φ(
p
1
k
1
p_{1}^{k_1}
p1k1)φ(
p
2
k
2
p_{2}^{k_2}
p2k2)…φ(
p
m
k
m
p_{m}^{k_m}
pmkm)
再结合上方p为质数时:φ(
p
k
p^k
pk)=
p
k
p^k
pk-
p
k
−
1
p^{k-1}
pk−1=
p
k
−
1
p^{k-1}
pk−1(p-1),可得:
φ(n) =
p
1
k
1
−
1
p_1^{k_1-1}
p1k1−1
(
p
1
−
1
)
(p_1-1)
(p1−1)
p
2
k
2
−
1
p_2^{k_2-1}
p2k2−1
(
p
2
−
1
)
(p_2-1)
(p2−1)…
p
m
k
m
−
1
p_m^{k_m-1}
pmkm−1
(
p
m
−
1
)
(p_m-1)
(pm−1)
接下来我们的任务就是讨论φ(n)何时为质数,何时为合数。
继续结合式子φ(n) =
p
1
k
1
−
1
p_1^{k_1-1}
p1k1−1
(
p
1
−
1
)
(p_1-1)
(p1−1)
p
2
k
2
−
1
p_2^{k_2-1}
p2k2−1
(
p
2
−
1
)
(p_2-1)
(p2−1)…
p
m
k
m
−
1
p_m^{k_m-1}
pmkm−1
(
p
m
−
1
)
(p_m-1)
(pm−1)进行讨论:
1.若n存在一个质因子 q ≥ 5 q\geq5 q≥5,那么式子中就存在一项为(q-1),已知q为质数且 q ≥ 5 q\geq5 q≥5,q必定为奇数,那么(q-1)必定为偶数,该偶数因子中一定有2,而且除了2还有另外的因子,所以此时的φ(n) 必定为合数。
2.那么我们接下来的任务就是讨论质因子2,3的情况:
关于2,那么在φ(n) 中的项为
2
k
−
1
2^{k-1}
2k−1 *(2-1),
当k>2时,
2
k
−
1
2^{k-1}
2k−1中包含因子4,所以φ(n) 必定为合数
关于3,在φ(n) 中的项为
3
k
−
1
3^{k-1}
3k−1 *(3-1),即
3
k
−
1
3^{k-1}
3k−1 *2,
已经有了一个因子2,只要
3
k
−
1
3^{k-1}
3k−1可以提供另一个因子,也就是k>1,就有φ(n) 必定为合数。
综上所述三种条件任满足其一都可以使得φ(n)必定为合数,反过来说也就是三个条件都不满足就可能为质数。
那么我们此时再看1,2,3,4,6,24的欧拉函数的情况:
φ(
1
1
1)=1,为质数;
φ(
2
2
2)=1,为质数;
φ(
3
3
3)=2,为质数;
φ(
4
4
4)=2,为质数;
φ(
6
6
6)=2,为质数;
φ(
24
24
24)=8,为合数;
也就是说只有1,2,3,4,6的欧拉函数为质数,其余皆为合数。
那么给定k时,我们输出的答案就是:k+4+[k>1]
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
int k;
cin>>k;
if(k==1)cout<<5<<endl;
else cout<<k+5<<endl;
}
}
4.推论:a为奇数时,φ(2a) = φ(2)*φ(a)=φ(a)。
2.正整数a,b,若d=gcd(a,b),则φ( a b ab ab) = φ(a)φ(b) d φ ( d ) \frac{d}{φ(d)} φ(d)d
证明
证明的思路与上方一致,都是进行唯一分解,再利用积性函数的性质来处理。
3.若b是质数,且b|a,则 φ(ab)=φ(a)b
证明
有条件可知,b为a的一个质因子,那么a就可以表示为
k
b
n
kb^n
kbn,且k与b满足互质关系,可得:
φ(a)=φ(
k
b
n
kb^n
kbn)=φ(k)φ(
b
n
b^n
bn)
又根据b为质数,式子进一步转化为:
φ(a)=φ(k)
b
n
−
1
(
b
−
1
)
b^{n-1}(b-1)
bn−1(b−1)
→
\rightarrow
→φ(k)=
φ
(
a
)
b
n
−
1
(
b
−
1
)
\frac{φ(a)}{b^{n-1}(b-1)}
bn−1(b−1)φ(a)
再讨论φ(ab),同理:
φ(ab)=φ(
k
b
n
+
1
kb^{n+1}
kbn+1)=φ(k)φ(
b
n
+
1
b^{n+1}
bn+1)=φ(k)
b
n
(
b
−
1
)
b^{n}(b-1)
bn(b−1)
结合两式可解得:
φ(ab)=
φ
(
a
)
b
n
−
1
(
b
−
1
)
\frac{φ(a)}{b^{n-1}(b-1)}
bn−1(b−1)φ(a)
b
n
(
b
−
1
)
b^{n}(b-1)
bn(b−1)=φ(a)b
证毕
三、求欧拉函数
1.φ(n) = n n n ∏ i = 1 m ( 1 − 1 p i ) \prod_{i=1}^{m} (1-\frac{1}{p_i}) ∏i=1m(1−pi1)
1.证明
对n进行唯一分解,可得n=
p
1
k
1
p_{1}^{k_1}
p1k1
p
2
k
2
p_{2}^{k_2}
p2k2…
p
m
k
m
p_{m}^{k_m}
pmkm,
同上方一样,利用互质关系质数性质,可得:
φ(n) =
p
1
k
1
p_1^{k_1}
p1k1
(
1
−
1
p
1
)
(1-\frac{1}{p_1})
(1−p11)
p
2
k
2
p_2^{k_2}
p2k2
(
1
−
1
p
2
)
(1-\frac{1}{p_2})
(1−p21)…
p
m
k
m
p_m^{k_m}
pmkm
(
1
−
1
p
m
)
(1-\frac{1}{p_m})
(1−pm1)
将式子进行简单整理,可得:
φ(n) =n
(
1
−
1
p
1
)
(1-\frac{1}{p_1})
(1−p11)
(
1
−
1
p
2
)
(1-\frac{1}{p_2})
(1−p21)…
(
1
−
1
p
m
)
(1-\frac{1}{p_m})
(1−pm1)
2.代码
typedef long long ll;
ll euler(ll n){ //返回euler(n)
ll res=n,a=n;
for(ll i=2;i*i<=a;i++){
if(a%i==0){
res=res/i*(i-1);//先进行除法是为了防止中间数据的溢出
while(a%i==0) a/=i;
}
}
if(a>1) res=res/a*(a-1);
return res;
}
2.递推打表
1.思路:
2.关键代码
const int N=1e6+10;
int primes[N], euler[N], cnt;
bool st[N];
void get_eulers(int n){ //欧拉筛的扩展
euler[1] = 1;
for (int i=2; i <= n; i++ ){
if ( !st[i] ){
primes[cnt++] = i;
euler[i] = i-1;
}
for ( int j=0; primes[j] <= n/i; j++ ){
st[ primes[j]*i ] = true;
if ( i % primes[j] == 0 ) {
euler[ i*primes[j] ] = euler[i] * primes[j];
break;
}
euler[ i*primes[j] ] = euler[i] * ( primes[j]-1 );
}
}
}
3.模板题·Farey Sequence
大意:给定一个数n(2<=n<= 1 0 6 10^6 106),求分母不大于n的既约真分数的个数
思路:
既约真分数,意味着分子分母为互质关系,且分子小于分母,很容易联想到欧拉函数,这道题就是求欧拉函数之和,不过不包含φ(1),因为分数
1
1
\frac{1}{1}
11不满足既约真分数的要求。
所以 F(n)=
∑
i
=
2
n
φ
(
i
)
\sum_{i=2}^n φ(i)
∑i=2nφ(i)
打表可过,注意范围,使用Long Long
代码:
#include<iostream>
using namespace std;
const int N=1e6+10;
long long primes[N], euler[N], cnt;
bool st[N];
void get_eulers(int n){ //欧拉筛的扩展
euler[1] = 1;
for (int i=2; i <= n; i++ ){
if ( !st[i] ){
primes[cnt++] = i;
euler[i] = i-1;
}
for ( int j=0; primes[j] <= n/i; j++ ){
st[ primes[j]*i ] = true;
if ( i % primes[j] == 0 ) {
euler[ i*primes[j] ] = euler[i] * primes[j];
break;
}
euler[ i*primes[j] ] = euler[i] * ( primes[j]-1 );
}
}
}
int main(){
get_eulers(1e6+8);
euler[0]=-1;
for(int i=1;i<1e6+5;i++)
euler[i]+=euler[i-1];
int t;
while(cin>>t&&t){
cout<<euler[t]<<endl;
}
}
4.例题·Longge 的问题
大意:给定n,求 ∑ i = 1 n \sum_{i=1}^n ∑i=1n g c d ( i , n ) gcd(i,n) gcd(i,n),(0<n<= 2 32 2^{32} 232)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
//const int N= 1e6;
//int euler[N];
//bool st[N];
//int primes[N];
//int cnt;
//void get_eulers(int n){
// euler[1] = 1;
// for (int i=2; i <= n; i++ ){
// if ( !st[i] ){
// primes[cnt++] = i;
// euler[i] = i-1;
// }
// for ( int j=0; primes[j] <= n/i; j++ ){
// st[ primes[j]*i ] = true;
// if ( i % primes[j] == 0 ) {
// euler[ i*primes[j] ] = euler[i] * primes[j];
// break;
// }
// euler[ i*primes[j] ] = euler[i] * ( primes[j]-1 );
// }
// }
//}
ll euler(ll x){
ll ans=x,tp=sqrt(x);
for(ll i=2;i<=tp;++i)
if(x%i==0) {
ans=ans-ans/i;
while(x%i==0) x/=i;
}
if(x>1) ans=ans-ans/x;
return ans;
}
int main(){
ll n;
// cin>>n;
scanf("%lld",&n);
// get_eulers(n);
ll ans=0,t=sqrt(n);
for(ll i=1;i<=t;i++){
if(n%i==0)ans+=i*euler(n/i)+(n/i)*euler(i);
}
if(t*t==n)ans-=t*euler(t);
// cout<<ans<<endl;
printf("%lld\n",ans);
return 0;
}