【详解】欧拉函数

互质与欧拉函数

互质

任意自然数 a , b a,b a,b,若 g c d ( a , b ) = 1 gcd(a,b)=1 gcd(a,b)=1,则称 a , b a,b a,b 互质。

对于三个数或更多个数,将 g c d ( a , b , c ) = 1 gcd(a,b,c)=1 gcd(a,b,c)=1 的情况称为 a , b , c a,b,c a,b,c 互质。把 g c d ( a , b ) = g c d ( b , c ) = g c d ( a , c ) = 1 gcd(a,b)=gcd(b,c)=gcd(a,c)=1 gcd(a,b)=gcd(b,c)=gcd(a,c)=1 称为两两互质,两者有明显的区别,显然,后者要求更高。

欧拉函数

1 ∼ N 1\sim N 1N 中与 N N N 互质的个数被称为欧拉函数,记为 φ ( N ) \varphi(N) φ(N)

在算术基本定理中, N = p 1 c 1 × p 2 c 2 × . . . × p m c m N=p_1^{c_1}\times p_2^{c_2}\times ...\times p_m^{c_m} N=p1c1×p2c2×...×pmcm p 1 , p 2 . . . p m p_1,p_2...p_m p1,p2...pm 为质数,则:

φ ( N ) = N × p 1 − 1 p 1 × p 2 − 1 p 2 × . . . × p m − 1 p m \varphi(N)=N\times \frac {p_1-1} {p_1}\times \frac {p_2-1} {p_2}\times...\times \frac {p_m-1} {p_m} φ(N)=N×p1p11×p2p21×...×pmpm1

证明:

p p p N N N 的质因子,则 1 ∼ N 1\sim N 1N p p p 的倍数有: p , 2 p , 3 p . . . ( N p ) × p p,2p,3p...(\frac N p)\times p p,2p,3p...(pN)×p,共 N p \frac N p pN (整除)个。同理,若 q q q 也是 N N N 的质因子,则 1 ∼ N 1\sim N 1N q q q 的倍数有: q , 2 q , 3 q . . . ( N q ) × q q,2q,3q...(\frac N q)\times q q,2q,3q...(qN)×q,共 N q \frac N q qN (整除)个。同时 p × q p\times q p×q 的倍数即被 p p p 排除了,又被 q q q 排除了,所有需要加回来。因此, 1 ∼ N 1\sim N 1N 中不与 N N N 含有共同质因子 p p p q q q 的个数为:

N − N q − N p + N p q = N × ( 1 − 1 p − 1 q + 1 p q ) = N × ( 1 − 1 p ) × ( 1 − 1 q ) N-{\frac N q}-{\frac N p}+{\frac N {pq}}=N\times (1-\frac 1 p-\frac 1 q+\frac 1 {pq})=N\times (1-\frac 1 p)\times (1-\frac 1 q) NqNpN+pqN=N×(1p1q1+pq1)=N×(1p1)×(1q1)

这种思想被称为容斥思想(后续会学习)。同理,可以得到 1 ∼ N 1\sim N 1N 中不与 N N N 含有共同因子的数的个数,也就是与 N N N 互质的个数。

根据欧拉函数的计算公式,就可以求解出欧拉函数。

【参考程序】

//求解n的欧拉函数
int phi(int n)
{
	int ans=n;
	for(int i=2;i<=sqrt(n);i++)
	{
		if(n%i==0)
		{
			ans=ans/i*(i-1);
			while(n%i==0) n/=i;
		}
	}
	if(n>1) ans=ans/n*(n-1);
	return ans;
}

时间复杂度 O ( N ) O(\sqrt N) O(N )

性质

性质 1 1 1 n > 1 n>1 n>1 1 ∼ n 1\sim n 1n 中与 n n n 互质的数的和为 n × φ ( n ) 2 \frac {n\times \varphi(n)} 2 2n×φ(n)

性质 2 2 2 a , b a,b a,b 互质,则 φ ( a b ) = φ ( a ) × φ ( b ) \varphi(ab)=\varphi(a)\times \varphi(b) φ(ab)=φ(a)×φ(b)

证明:

因为 g c d ( n , x ) = g c d ( n , n − x ) gcd(n,x)=gcd(n,n-x) gcd(n,x)=gcd(n,nx) (九章算术.更相减损术), n n n x 、 n − x x、n-x xnx 不互质,因此与 n n n 不互质的数是成对出现的,和为 n n n ,平均值为 n 2 \frac n 2 2n,则与 n n n 互质的数的平均值为 n 2 \frac n 2 2n 1 ∼ n 1\sim n 1n 中与 n n n 互质的数的和为 n × φ ( n ) 2 \frac {n\times \varphi(n)} 2 2n×φ(n) ,性质 1 1 1 成立。

根据欧拉函数的计算公式,对 a , b a,b a,b 分解质因数,直接可以得到性质 2 2 2

积性函数

如果 a , b a,b a,b 互质,有 f ( a , b ) = f ( a ) × f ( b ) f(a,b)=f(a)\times f(b) f(a,b)=f(a)×f(b),那么称函数 f f f 为积性函数。

性质

性质 3 3 3 f f f 为积性函数,且在算术定理中, n = ∏ i = 1 m p i c i n=\prod_{i=1}^m p_i^{c_i} n=i=1mpici ,则 f ( n ) = ∏ i = 1 m f ( p i c i ) f(n)=\prod_{i=1}^m f(p_i^{c_i}) f(n)=i=1mf(pici)

性质 4 4 4 p p p 是质数,若 p ∣ n p|n pn p 2 ∣ n p^2|n p2n,则 φ ( n ) = φ ( n p ) × p \varphi(n)=\varphi(\frac n p)\times p φ(n)=φ(pn)×p

性质 5 5 5 p p p 是质数,若 p ∣ n p|n pn p 2 p^2 p2 不能整除 n n n ,则 φ ( n ) = φ ( n p ) × ( p − 1 ) \varphi(n)=\varphi(\frac n p)\times (p-1) φ(n)=φ(pn)×(p1)

证明: 略,可参考《算法竞赛进阶指南》 0 x 32 0x32 0x32 约数。

例 1:「SDOI2008」仪仗队

【题目描述】

作为体育委员, C C C 君负责这次运动会仪仗队的训练。仪仗队是由学生组成的 N ∗ N N * N NN的方阵,为了保证队伍在行进中整齐划一, C C C 君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如下图)。

现在, C C C 君希望你告诉他队伍整齐时能看到的学生人数。

【输入】

共一个数 N N N

【输出】

共一个数,即 C C C 君应看到的学生人数。

【样例输入】

4

【样例输出】

9

【数据范围】

对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 40000 1 ≤ N ≤ 40000 1N40000

【算法分析】

设左下角为 ( 0 , 0 ) (0,0) (0,0) ,右上角为 ( N − 1 , N − 1 ) (N-1,N-1) (N1,N1)

对于 ( x , y ) (x,y) (x,y) ,和 ( 0 , 0 ) (0,0) (0,0) 组成的线的斜率为 y x \frac y x xy ,若 x , y x,y x,y 存在最大公约数 p ( p > 1 ) p(p>1) p(p>1),那么 ( x p , y p ) (\frac x p,\frac y p) (px,py) ( 0 , 0 ) (0,0) (0,0) 斜率也为 y x \frac y x xy ( x p , y p ) (\frac x p,\frac y p) (px,py) ( x , y ) (x,y) (x,y) ( 0 , 0 ) (0,0) (0,0) 在同一条线上,且在 ( x , y ) (x,y) (x,y) 之前, ( 0 , 0 ) (0,0) (0,0) 就只能看到 ( x p , y p ) (\frac x p,\frac y p) (px,py)

因此,除了 ( 1 , 0 ) , ( 0 , 1 ) , ( 1 , 1 ) (1,0),(0,1),(1,1) (1,0),(0,1),(1,1),$(x,y) $ 能被看到必须满足 g c d ( x , y ) = 1 , 1 ≤ x , y ≤ N − 1 , x ≠ y gcd(x,y)=1,1\le x,y\le N-1,x\neq y gcd(x,y)=11xyN1x=y

同时,能看到的人数关于 ( 0 , 0 ) (0,0) (0,0) ( N − 1 , N − 1 ) (N-1,N-1) (N1,N1) 的直线对称,因此可以只需要考虑一半即可,即 1 ≤ x < y ≤ N − 1 1\le x< y\le N-1 1x<yN1 。对于任意 y   ( 2 ≤ y ≤ N − 1 ) y\ (2\le y\le N-1) y (2yN1) 有多少 x x x 满足 g c d ( x , y ) = 1 gcd(x,y)=1 gcd(x,y)=1,且 x < y x<y x<y 。这样的 x x x 个数就是 φ ( y ) \varphi(y) φ(y)

因此,最后的答案: a n s = 3 + 2 × ( φ ( 2 ) + φ ( 3 ) + . . . + φ ( N − 1 ) ) ans=3+2\times(\varphi(2)+\varphi(3)+...+\varphi(N-1)) ans=3+2×(φ(2)+φ(3)+...+φ(N1))

2 ∼ ( N − 1 ) 2\sim (N-1) 2(N1) 的欧拉函数可以使用朴素做法,逐个求解,时间复杂度为 O ( N N ) O(N\sqrt N) O(NN )

利用埃氏筛法,按照欧拉函数的公式,在 O ( N log ⁡ N ) O(N\log N) O(NlogN) 的时间求出,

int phi[100010];
void euler(int n)
{
	for(int i=2;i<=n;i++)	phi[i]=i;
	for(int i=2;i<=n;i++)
	{
		if(phi[i]==i)				//质数
		{
			for(int j=i;j<=n;j+=i)	//i,i+i,i+2i...都包含i的质因子
				phi[j]=phi[j]/i*(i-1);
		}
	}
}

线性筛法中,每个合数 n n n 只会被它最小的质因子 p p p 筛一次,可以利用性质 4 4 4 和性质 5 5 5 ,用 φ ( n p ) \varphi(\frac n p) φ(pn) 递推 φ ( n ) \varphi(n) φ(n) ,事件复杂度为 O ( N ) O(N) O(N)

方法一:朴素算法

#include <bits/stdc++.h>
using namespace std;
int phi(int n)  //求解n的欧拉函数
{
    int ans=n;
    for(int i=2;i<=sqrt(n);i++)
    {
        if(n%i==0)
        {
            ans=ans/i*(i-1);
            while(n%i==0) n/=i;
        }
    }
    if(n>1) ans=ans/n*(n-1);
    return ans;
}
 
int main()
{
    int n,ans=0;
    cin>>n;
    if(n==1) {cout<<0<<endl;return 0;}
    for(int i=2;i<=n-1;i++)
        ans+=phi(i);
    cout<<3+2*ans<<endl;
    return 0;
} 

方法二:线性筛法

#include <bits/stdc++.h>
using namespace std;
const int N=40010;
int  v[N],prime[N],phi[N];
void euler(int n)
{
	memset(v,0,sizeof(v));	//保存最小质因子 
	int k=0;				//质数个数 
	for(int i=2;i<=n;i++)
	{
		if(v[i]==0)
		{
			v[i]=i;
			prime[++k]=i;
			phi[i]=i-1;		//质数i的欧拉函数为i-1 
		}
		//给当前的数i乘以更小的质因子
		for(int j=1;j<=k;j++)
		{
			if(prime[j]>v[i]||prime[j]>n/i) break;
			v[i*prime[j]]=prime[j];					//更新i*prime[j]的最小质因子
			phi[i*prime[j]]=phi[i]*(i%prime[j]?prime[j]-1:prime[j]);	//使用性质4和性质5
		} 
	 } 
}
int main()
{
	int n,ans=0;
	cin>>n;
	if(n==1) {cout<<0<<endl;return 0;}
	euler(n);
	for(int i=2;i<=n-1;i++)
		ans+=phi[i];
	cout<<3+2*ans<<endl; 
    return 0;
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值