【数论】欧拉函数

欧拉函数

一、定义

对于正整数 n n n,在小于 n n n 的正整数中与 n n n 互质的数的数目是欧拉函数,记作 φ ( n ) \varphi(n) φ(n)

二、性质

性质一

根据定义,我们可以得出公式:

φ ( n ) = ∑ i = 1 n − 1 [ gcd ⁡ ( i , n ) = 1 ] \varphi(n)=\sum_{i=1}^{n-1}[\gcd(i,n)=1] φ(n)=i=1n1[gcd(i,n)=1]

性质二

φ ( n ) = n ∏ p ∣ n p ∈ P ( 1 − 1 p ) \varphi(n)=n\prod_{\substack{p|n\\p\in\mathbb{P}}}\left(1-\frac{1}{p}\right) φ(n)=npnpP(1p1)

其中, P \mathbb{P} P 为质数集。

下面证明该性质:

如果 p p p n n n 质因数,那么有 1 p \frac{1}{p} p1 的数是 p p p 的倍数, 即有 ( 1 − 1 p ) \left(1-\frac{1}{p}\right) (1p1) 的数与 n n n 互质,那么与 n n n 的质因数均不相等的数的个数就是 n ( 1 − 1 p 1 ) ( 1 − 1 p 2 ) . . . ( 1 − 1 p k ) n\left(1-\frac{1}{p_1}\right)\left(1-\frac{1}{p_2}\right)...\left(1-\frac{1}{p_k}\right) n(1p11)(1p21)...(1pk1),得证。

性质三

如果 n n n 是质数,小于等于 n n n 的数均与 n n n 互质,那么有 φ ( n ) = n − 1 \varphi(n)=n-1 φ(n)=n1

性质四

如果 n n n m m m 互质,那么有

φ ( n m ) = φ ( n ) φ ( m ) \varphi(nm)=\varphi(n)\varphi(m) φ(nm)=φ(n)φ(m)

下面证明该性质:

φ ( n ) φ ( m ) = n ∏ p ∣ n p ∈ P ( 1 − 1 p ) m ∏ p ∣ m p ∈ P ( 1 − 1 p ) = n m ∏ p ∣ n p ∈ P ( 1 − 1 p ) ∏ p ∣ m p ∈ P ( 1 − 1 p ) \varphi(n)\varphi(m)=n\prod_{\substack{p|n\\p\in\mathbb{P}}}\left(1-\frac{1}{p}\right)m\prod_{\substack{p|m\\p\in\mathbb{P}}}\left(1-\frac{1}{p}\right)=nm\prod_{\substack{p|n\\p\in\mathbb{P}}}\left(1-\frac{1}{p}\right)\prod_{\substack{p|m\\p\in\mathbb{P}}}\left(1-\frac{1}{p}\right) φ(n)φ(m)=npnpP(1p1)mpmpP(1p1)=nmpnpP(1p1)pmpP(1p1)

因为 n n n m m m 互质,所以 n m nm nm 的质因数就是 n n n 的质因数与 m m m 的质因数的交集,所以

φ ( n ) φ ( m ) = n m ∏ p ∣ n m p ∈ P ( 1 − 1 p ) = φ ( n m ) \varphi(n)\varphi(m)=nm\prod_{\substack{p|nm\\p\in\mathbb{P}}}\left(1-\frac{1}{p}\right)=\varphi(nm) φ(n)φ(m)=nmpnmpP(1p1)=φ(nm)

性质五

n > 2 n>2 n>2 时, φ ( n ) \varphi(n) φ(n) 是偶数。

下面证明该性质:

gcd ⁡ ( n , i ) = 1 \gcd(n,i)=1 gcd(n,i)=1 时, gcd ⁡ ( n , n − i ) = 1 \gcd(n,n-i)=1 gcd(n,ni)=1

i = n − i i=n-i i=ni,则 n = 2 i n=2i n=2i n n n i i i 不互质。

所以 φ ( n ) \varphi(n) φ(n) 总为偶数。( n > 2 n>2 n>2

性质六

在区间 [ 1 , n ] [1,n] [1,n] 中所有与 n n n 互质的数的和为 φ ( n ) n 2 \frac{\varphi(n)n}{2} 2φ(n)n

下面证明该性质:

根据性质五,如果 gcd ⁡ ( n , i ) = 1 \gcd(n,i)=1 gcd(n,i)=1,那么有 gcd ⁡ ( n , n − i ) = 1 \gcd(n,n-i)=1 gcd(n,ni)=1 i i i n − i n-i ni 的和是 n n n,这样的数对的个数是 φ ( n ) 2 \frac{\varphi(n)}{2} 2φ(n) 个,所以和为 φ ( n ) n 2 \frac{\varphi(n)n}{2} 2φ(n)n

性质七

φ ( n 2 ) = n φ ( n ) \varphi(n^2)=n\varphi(n) φ(n2)=nφ(n)

下面证明该性质:

因为 n 2 n^2 n2 的质因数和 n n n 的质因数相同,因此

φ ( n 2 ) = n 2 ∏ p ∣ n 2 p ∈ P ( 1 − 1 p ) = n 2 ∏ p ∣ n p ∈ P ( 1 − 1 p ) = n × n ∏ p ∣ n p ∈ P ( 1 − 1 p ) = n φ ( n ) \varphi(n^2)=n^2\prod_{\substack{p|n^2\\p\in\mathbb{P}}}\left(1-\frac{1}{p}\right)=n^2\prod_{\substack{p|n\\p\in\mathbb{P}}}\left(1-\frac{1}{p}\right)=n\times n\prod_{\substack{p|n\\p\in\mathbb{P}}}\left(1-\frac{1}{p}\right)=n\varphi(n) φ(n2)=n2pn2pP(1p1)=n2pnpP(1p1)=n×npnpP(1p1)=nφ(n)

三、求欧拉函数

快速求欧拉函数

根据性质二,我们可以在 O ( n ) O(\sqrt{n}) O(n ) 的时间复杂度内完成。

代码如下:

void phi(int n)
{
	int ans = n;
	for (int i = 2; i <= n / i; 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;
}

线性求欧拉函数

根据性质三、性质四和性质七,我们就可以线性求欧拉函数。

  • 如果 n n n 为质数,那么 φ ( n ) = n − 1 \varphi(n)=n-1 φ(n)=n1
  • 如果 m m m n n n 的最小平方因子,那么 φ ( n ) = m φ ( n m ) \varphi(n)=m\varphi(\frac{n}{m}) φ(n)=mφ(mn)
  • 如果 m m m n n n 的最小质因数,那么 φ ( n ) = φ ( m ) φ ( n m ) = ( m − 1 ) φ ( n m ) \varphi(n)=\varphi(m)\varphi(\frac{n}{m})=(m-1)\varphi(\frac{n}{m}) φ(n)=φ(m)φ(mn)=(m1)φ(mn)

以下是一个可以参考的代码:

phi[1] = 1;
for (int i = 2; i <= n; i ++ )
{
	if (!vis[i])
	{
		prime[ ++ cnt] = i;
		phi[i] = i - 1;
	}
	for (int j = 1; prime[j] <= n / i; j ++ )
	{
		vis[i * prime[j]] = 1;
		if (i % prime[j] == 0)
		{
			phi[i * prime[j]] = prime[j] * phi[i];
			break;
		}
		phi[i * prime[j]] = (prime[j] - 1) * phi[i];
	}
}

四、例题

P2158 [SDOI2008] 仪仗队

我们假设坐标的下标从 0 0 0 开始。

设一个人的位置是 ( x , y ) (x,y) (x,y) ,若 g c d ( x , y ) = k ≠ 1 gcd(x,y)=k\not=1 gcd(x,y)=k=1,那么在坐标 ( x k , y k ) (\frac{x}{k},\frac{y}{k}) (kx,ky) 的人会将这个人遮挡,所以这道题其实就是在求 gcd ⁡ ( x , y ) = 1 \gcd(x,y)=1 gcd(x,y)=1 的个数,公式如下:

∑ i = 0 n − 1 ∑ j = 0 n − 1 [ gcd ⁡ ( i , j ) = 1 ] \sum_{i=0}^{n-1}\sum_{j=0}^{n-1}[\gcd(i,j)=1] i=0n1j=0n1[gcd(i,j)=1]

通过观察图片可以发现,图片延 y = x y=x y=x 对称,所以原式

= ∑ i = 0 n − 1 ∑ j = 0 i − 1 [ gcd ⁡ ( i , j ) = 1 ] + ∑ i = 0 n − 1 ∑ j = i i [ gcd ⁡ ( i , j ) = 1 ] + ∑ i = 0 n − 1 ∑ j = i + 1 n − 1 [ gcd ⁡ ( i , j ) = 1 ] =\sum_{i=0}^{n-1}\sum_{j=0}^{i-1}[\gcd(i,j)=1]+\sum_{i=0}^{n-1}\sum_{j=i}^{i}[\gcd(i,j)=1]+\sum_{i=0}^{n-1}\sum_{j=i+1}^{n-1}[\gcd(i,j)=1] =i=0n1j=0i1[gcd(i,j)=1]+i=0n1j=ii[gcd(i,j)=1]+i=0n1j=i+1n1[gcd(i,j)=1]

= 2 ∑ i = 0 n − 1 ∑ j = 0 i − 1 [ gcd ⁡ ( i , j ) = 1 ] + 1 =2\sum_{i=0}^{n-1}\sum_{j=0}^{i-1}[\gcd(i,j)=1]+1 =2i=0n1j=0i1[gcd(i,j)=1]+1

= 2 ∑ i = 1 n − 1 φ ( i ) + 1 =2\sum_{i=1}^{n-1}\varphi(i)+1 =2i=1n1φ(i)+1

需要注意,当 n = 1 n=1 n=1 时,答案为 0 0 0

代码如下:

#include <bits/stdc++.h>

using namespace std;

const int N = 1000005;

int n;
long long prime[N], vis[N], phi[N], cnt;

int main()
{
	scanf("%d", &n);
	if (n == 1)
	{
	    puts("0");
	    return 0;
	}
	phi[1] = 1;
	for (int i = 2; i <= n; i ++ )
	{
		if (!vis[i])
		{
			prime[ ++ cnt] = i;
			phi[i] = i - 1;
		}
		for (int j = 1; prime[j] <= n / i; j ++ )
		{
			vis[i * prime[j]] = 1;
			if (i % prime[j] == 0)
			{
				phi[i * prime[j]] = prime[j] * phi[i];
				break;
			}
			phi[i * prime[j]] = (prime[j] - 1) * phi[i];
		}
	}
	long long ans = 0;
	for (int i = 1; i < n; i ++ )
		ans += phi[i];
	printf("%d\n", 2 * ans + 1);
	
    return 0;
}

P2568 GCD

枚举每一个质数 p p p,求 gcd ⁡ ( x , y ) = p \gcd(x,y)=p gcd(x,y)=p 的情况,此时一定有 p ∣ x p|x px p ∣ y p|y py,那么 gcd ⁡ ( x , y ) = p \gcd(x,y)=p gcd(x,y)=p 等价于 gcd ⁡ ( x p , y p ) = 1 \gcd(\frac{x}{p},\frac{y}{p})=1 gcd(px,py)=1,于是就有公式:

∑ p ∈ P ∑ i = 1 n ∑ j = 1 n [ gcd ⁡ ( i , j ) = p ] \sum_{p\in\mathbb{P}}\sum_{i=1}^{n}\sum_{j=1}^{n}[\gcd(i,j)=p] pPi=1nj=1n[gcd(i,j)=p]

= ∑ p ∈ P ∑ i = 1 ⌊ n p ⌋ ∑ j = 1 ⌊ n p ⌋ [ gcd ⁡ ( i , j ) = 1 ] =\sum_{p\in\mathbb{P}}\sum_{i=1}^{\left\lfloor\frac{n}{p}\right\rfloor}\sum_{j=1}^{\left\lfloor\frac{n}{p}\right\rfloor}[\gcd(i,j)=1] =pPi=1pnj=1pn[gcd(i,j)=1]

= ∑ p ∈ P ( ∑ i = 1 ⌊ n p ⌋ ∑ j = 1 i − 1 [ gcd ⁡ ( i , j ) = 1 ] + ∑ i = 1 ⌊ n p ⌋ ∑ j = i i [ gcd ⁡ ( i , j ) = 1 ] + ∑ i = 1 ⌊ n p ⌋ ∑ j = i + 1 ⌊ n p ⌋ [ gcd ⁡ ( i , j ) = 1 ] ) =\sum_{p\in\mathbb{P}}\left(\sum_{i=1}^{\left\lfloor\frac{n}{p}\right\rfloor}\sum_{j=1}^{i-1}[\gcd(i,j)=1]+\sum_{i=1}^{\left\lfloor\frac{n}{p}\right\rfloor}\sum_{j=i}^{i}[\gcd(i,j)=1]+\sum_{i=1}^{\left\lfloor\frac{n}{p}\right\rfloor}\sum_{j=i+1}^{\left\lfloor\frac{n}{p}\right\rfloor}[\gcd(i,j)=1]\right) =pP i=1pnj=1i1[gcd(i,j)=1]+i=1pnj=ii[gcd(i,j)=1]+i=1pnj=i+1pn[gcd(i,j)=1]

= ∑ p ∈ P ( 2 ∑ i = 1 ⌊ n p ⌋ ∑ j = 1 i − 1 [ gcd ⁡ ( i , j ) = 1 ] + 1 ) =\sum_{p\in\mathbb{P}}\left(2\sum_{i=1}^{\left\lfloor\frac{n}{p}\right\rfloor}\sum_{j=1}^{i-1}[\gcd(i,j)=1]+1\right) =pP 2i=1pnj=1i1[gcd(i,j)=1]+1

= ∑ p ∈ P [ 2 ∑ i = 1 ⌊ n p ⌋ ( φ ( i ) − 1 ) + 1 ] =\sum_{p\in\mathbb{P}}\left[2\sum_{i=1}^{\left\lfloor\frac{n}{p}\right\rfloor}(\varphi(i)-1)+1\right] =pP 2i=1pn(φ(i)1)+1

= ∑ p ∈ P ( 2 ∑ i = 1 ⌊ n p ⌋ φ ( i ) − 1 ) =\sum_{p\in\mathbb{P}}\left(2\sum_{i=1}^{\left\lfloor\frac{n}{p}\right\rfloor}\varphi(i)-1\right) =pP 2i=1pnφ(i)1

对于倒数第 2 2 2 个式子,由于与 1 1 1 互质的数的个数 0 0 0 φ ( 1 ) = 1 \varphi(1)=1 φ(1)=1,需要减 1 1 1

#include <bits/stdc++.h>

using namespace std;

const int N = 10000005;

int n;
long long prime[N], vis[N], phi[N], Phi[N], cnt;

int main()
{
	scanf("%d",n);
	phi[1] = 1;
	for(int i = 2; i <= n; i ++ )
	{
		if(!vis[i])
		{
			prime[ ++ cnt] = i;
			phi[i] = i - 1;
		}
		for(int j = 1; prime[j] <= n / i; j ++ )
		{
			vis[i * prime[j]] = 1;
			if(i % prime[j] == 0)
			{
				phi[i * prime[j]] = prime[j] * phi[i];
				break;
			}
			phi[i * prime[j]] = (prime[j] - 1) * phi[i];
		}
	}
	long long ans = 0;
	for(int i = 1; i < n; i ++ )
	{
		Phi[i] = Phi[i - 1] + phi[i];
	}
	for(int i = 1; i <= cnt; i ++ )
	{
		ans += 2 * Phi[n / prime[i]] - 1;
	}
	printf("%d\n", ans);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值