【详解】欧拉函数

互质与欧拉函数

互质

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

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

欧拉函数

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

在算术基本定理中,N=p1c1×p2c2×...×pmcmN=p_1^{c_1}\times p_2^{c_2}\times ...\times p_m^{c_m}N=p1c1×p2c2×...×pmcmp1,p2...pmp_1,p_2...p_mp1,p2...pm 为质数,则:

φ(N)=N×p1−1p1×p2−1p2×...×pm−1pm\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

证明:

pppNNN 的质因子,则 1∼N1\sim N1Nppp 的倍数有:p,2p,3p...(Np)×pp,2p,3p...(\frac N p)\times pp,2p,3p...(pN)×p,共 Np\frac N ppN (整除)个。同理,若 qqq 也是 NNN 的质因子,则 1∼N1\sim N1Nqqq 的倍数有:q,2q,3q...(Nq)×qq,2q,3q...(\frac N q)\times qq,2q,3q...(qN)×q,共 Nq\frac N qqN (整除)个。同时 p×qp\times qp×q 的倍数即被 ppp 排除了,又被 qqq 排除了,所有需要加回来。因此,1∼N1\sim N1N 中不与 NNN 含有共同质因子 pppqqq 的个数为:

N−Nq−Np+Npq=N×(1−1p−1q+1pq)=N×(1−1p)×(1−1q)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∼N1\sim N1N 中不与 NNN 含有共同因子的数的个数,也就是与 NNN 互质的个数。

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

【参考程序】

//求解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)

性质

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

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

证明:

因为 gcd(n,x)=gcd(n,n−x)gcd(n,x)=gcd(n,n-x)gcd(n,x)=gcd(n,nx) (九章算术.更相减损术),nnnx、n−xx、n-xxnx 不互质,因此与 nnn 不互质的数是成对出现的,和为 nnn ,平均值为 n2\frac n 22n,则与 nnn 互质的数的平均值为 n2\frac n 22n1∼n1\sim n1n 中与 nnn 互质的数的和为 n×φ(n)2\frac {n\times \varphi(n)} 22n×φ(n) ,性质 111 成立。

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

积性函数

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

性质

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

性质 444ppp 是质数,若 p∣np|npnp2∣np^2|np2n,则 φ(n)=φ(np)×p\varphi(n)=\varphi(\frac n p)\times pφ(n)=φ(pn)×p

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

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

例 1:「SDOI2008」仪仗队

【题目描述】

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

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

【输入】

共一个数 NNN

【输出】

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

【样例输入】

4

【样例输出】

9

【数据范围】

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

【算法分析】

设左下角为 (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) 组成的线的斜率为 yx\frac y xxy ,若 x,yx,yx,y 存在最大公约数 p(p>1)p(p>1)p(p>1),那么(xp,yp)(\frac x p,\frac y p)(px,py)(0,0)(0,0)(0,0) 斜率也为 yx\frac y xxy(xp,yp)(\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) 就只能看到 (xp,yp)(\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) $ 能被看到必须满足 gcd(x,y)=1,1≤x,y≤N−1,x≠ygcd(x,y)=1,1\le x,y\le N-1,x\neq ygcd(x,y)=11xyN1x=y

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

因此,最后的答案:ans=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(NN)O(N\sqrt N)O(NN)

利用埃氏筛法,按照欧拉函数的公式,在 O(Nlog⁡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);
		}
	}
}

线性筛法中,每个合数 nnn 只会被它最小的质因子 ppp 筛一次,可以利用性质 444 和性质 555 ,用 φ(np)\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;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值