欧拉函数及其扩展

本文介绍了欧拉函数的基本概念,包括其性质和欧拉定理,展示了如何利用欧拉函数求解大数模运算和线性同余方程,并提供了欧拉筛和杜教筛在求欧拉函数中的应用,以及在洛谷问题中的实例代码。
摘要由CSDN通过智能技术生成

给出定义:

        ​​​​\phi (x) = \sum_{i = 1}^{n}[gcd(i,n) = 1]

欧拉函数定义为不超过n且与n互素的正整数的个数。

有以下性质:

  1. 设p和q是互素的正整数,有 \Phi (pq) = \Phi (p) \Phi(q)
  2. 若n为正整数,那么 n = \sum_{d|n}^{}(d)

利用欧拉函数我们可以推导出欧拉定理,即

        a^{\Phi (m)} \equiv 1\left ( mod \ m\right),其中m是一个正整数,a为整数,且a与m互素。

欧拉定理可用于求大数的模,求解线性同余方程等。此外,欧拉定理的扩展可以用来实现降幂。现给出扩展欧拉定理:

        a^{b} \equiv \left\{\begin{matrix} a^{b \ mod \ \Phi (m)},&gcd(a,m) = 1, \\ a^{b}, & gcd(a,m) \neq 1,b < \Phi (m),(mod \ m),\\ a^{\left ( b \ mod(\Phi (m))+ \Phi (m) \right )} ,& gcd(a,m)\neq 1,b \geq \Phi (m) ,\end{matrix}\right.

此外,由于欧拉函数为积性函数,所以可以用欧拉筛在O\left ( n \right )时间复杂度下求解\sum_{i = 1}^{n}\Phi (i)。此外,更快的方式为杜教筛,时间复杂度为O\left ( n^{\frac{2}{3}} \right )

例题:仪仗队(洛谷 P2158)

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6;
bool vst[N];
int prm[N],cnt,phi[N],sum[N];
void sieve() {
	phi[1] = 1;
	for(int i = 2; i <= N; i ++) {
		if(!vst[i]) {
			phi[i] = i - 1;
			prm[cnt ++] = i;
		}
		for(int j = 0; j < cnt; j ++) {
			if(i * prm[j] > N) break;
			vst[i * prm[j]] = 1;
			if(i % prm[j] == 0) {
				phi[i * prm[j]] = phi[i] * prm[j];
				break;
			}
			phi[i * prm[j]] = phi[i] * phi[prm[j]];
		}
	}
}
void slove() {
	sieve();
	sum[1] = 1;
	for(int i = 2; i <= N; i ++) sum[i] = sum[i - 1] + phi[i];
	int n;
	cin>>n;
	if(n == 1) cout<<0<<endl;
	else cout<<2 * sum[n - 1] + 1;
}
int main() {
	ios::sync_with_stdio(0);
	slove();
	return 0;
} 

例题:【模板】扩展欧拉定理(洛谷 P5091)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll phi = 1; 
ll m,a,b;
string bb;
ll ksm(ll a,ll b) {
	ll res = 1;
	while(b) {
		if(b&1) res = (res * a) % m;
		a = (a * a) % m,b >>= 1;
	}
	return res % m;
}
int euler(int n) {
	int ans = n;
	for(int p = 2; p * p <= n; p ++) {
		if(n % p == 0) {
			ans = ans / p * (p - 1);
			while(n % p == 0) {
				n /= p;
			}
		}
	}
	if(n != 1) ans = ans / n * (n - 1);
	return ans;
}
void slove() {
	cin>>a>>m;
	phi = euler(m);
	cin>>bb;
	bool f = false;
	for(auto c : bb) {
		b = b * 10 + c - '0';
		if(b >= phi) f = true,b %= phi;
	}
	if(f) b += phi;
	cout<<ksm(a,b);
} 
int main() {
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	slove();
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值