欧拉函数

欧拉函数φ(n)计算小于n且与n互质的正整数个数,它是积性函数,拥有多种性质,如φ(nm)=φ(n)φ(m) (gcd(n,m)=1)。欧拉定理表明,对于互质的a和n,aφ(n) ≡ 1 mod n。常用求法包括筛法和针对大数的计算,常见于数论问题,尤其在计算逆元时。" 116970915,10540856,Linux下使用一个定时器模拟多个定时器功能,"['Linux定时器', '并发编程', '操作系统']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义

在数论,对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目(φ(1)=1)(\varphi(1)=1)φ(1)=1。此函数以其首名研究者欧拉命名(Euler′stotientfunction)(Euler's totient function)(Eulerstotientfunction),它又称为Euler′stotientfunction、φEuler's totient function、\varphiEulerstotientfunctionφ函数、欧拉商数等。 例如φ(8)=4\varphi(8)=4φ(8)=4,因为1,3,5,7均和8互质。——来自百度百科。

其实百度百科这次说的比较明白,就是1-n中与n互质的数的个数,我们用φ(n)\varphi(n)φ(n)来表示。

性质

以下性质和定理不涉及证明。

  1. 欧拉函数是积性函数。即:φ(nm)=φ(n)φ(m)\varphi(nm)=\varphi(n)\varphi(m)φ(nm)=φ(n)φ(m),其中gcd(n,m)=1gcd(n,m)=1gcd(n,m)=1

  2. 当n为奇数时,φ(2n)=φ(n)\varphi(2n)=\varphi(n)φ(2n)=φ(n)

  3. 当n为质数时,φ(n)=n−1\varphi(n)=n-1φ(n)=n1

  4. φ(1)=1\varphi(1)=1φ(1)=1

  5. 欧拉定理:对于互质的正整数aaannn,有aφ(n)≡1modna^\varphi(n) \equiv 1 mod naφ(n)1modn。因此此定理也用来求逆元。

  6. n=pkn=p^kn=pk,则φ(n)=(p−1)×pk−1\varphi(n)=(p-1)×p^{k-1}φ(n)=(p1)×pk1

  7. n=p1k1×p2k2×...×pmkmn=p1^{k1} × p2^{k2} × ... × pm^{km}n=p1k1×p2k2×...×pmkm,则φ(n)=n×(1−1p1)×(1−1p2)...×(1−1pm)\varphi(n)=n×(1-\frac{1}{p1})×(1-\frac{1}{p2})...×(1-\frac{1}{pm})φ(n)=n×(1p11)×(1p21)...×(1pm1)

求法

其实求法的话,在性质里面基本都提到了,所以只提供几种针对不同题目的求法。

1.筛法

对于题目中要用到好多的欧拉函数的问题,我们需要提前预处理出每一个数的欧拉函数,然后在O(1)O(1)O(1)时间内回答。

筛法主要是修改自线性素数筛,结合欧拉函数的性质就能筛出欧拉函数。

代码实现:

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

2.单个求

有的题目比较良心,只让你求一个数的欧拉函数,但是不太良心的是这个数特别大。所以我们考虑怎么求一个大数的欧拉函数。

首先,可以O((n))O(\sqrt(n))O((n))的时间内判断一个数是否为质数,由欧拉函数的性质我们就可以知道质数的欧拉函数就是本身减一。如果不是质数,那么我们就用欧拉函数的计算公式:性质7。

对于一个数,我们没必要把质数表打出来,只需要O((n))O(\sqrt(n))O((n))的时间内枚举质数就好,然后不断的whilewhilewhile判断下去,期望的时间复杂度为O((n)logn)O(\sqrt(n)logn)O((n)logn)

代码实现

unsigned long long phi(unsigned long long x) {
	double ans = x;
	for(unsigned long long i=1; i<=top; i++) {
		if(x%prime[i])
			continue;
		while(x%prime[i]==0)
			x /= prime[i];
		ans = ans * (1-1.0/prime[i]);
	}
	return ans;
}

后记

欧拉函数还是比较重要的,在做题的时候如果发现找规律的话,就耐心的找一下。

不过最重要的还是要对数字敏感,体现在欧拉函数上就是,看到输入质数,输出减一的,应自然而然的联想到欧拉函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值