拓展欧拉定理

基础概念

欧拉定理

对于正整数 \(a\)\(m\),若满足 \(gcd(a,m)=1\),则 \(a^{\varphi(m)}\equiv1~(mod~m)\)\(\varphi(m)\)\(m\) 的欧拉函数。

拓展欧拉定理

\((mod~m)\) 的前提下,

\[a^b\equiv\begin{cases} a^b&,b<\varphi(m)\\ a^{b~mod~\varphi(m)+\varphi(m)}&,b\ge\varphi(m) \end{cases} \]

利用拓展欧拉定理,在求大次幂 \(a^b\) 时,可以先降幂,再用快速幂求解。步骤:

  • 先求出 \(m\) 的欧拉函数。见博客 欧拉函数
  • 再利用拓展欧拉定理进行降幂,代码如下:
string b;    // b是幂,因为很大,所以用字符串存

// 降幂 
int depow(int phi)
{
	bool flag = false;
	ll sum = 0;
	for (char ch : b)
	{
		sum = sum * 10 + ch - '0';
		if (sum >= phi)
		{
			sum %= phi;
			flag = true;
		}
	}
	
	if (flag)    sum += phi;
	
	return sum;
}
  • 再用快速幂求解。见博客 快速幂

例题

P5091 【模板】扩展欧拉定理

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

int a, m;
string b;

// 求欧拉函数 
int get_phi(int n)
{
	ll res = n;
	for (int i = 2; (ll)i * i <= n; ++i)
	{
		if (n % i == 0)
		{
			res = res * (i - 1) / i;
			while (n % i == 0)    n /= i;
		}
	}
	
	if (n > 1)    res = res * (n - 1) / n;
	
	return res;
}

// 降幂 
int depow(int phi)
{
	bool flag = false;
	ll sum = 0;
	for (char ch : b)
	{
		sum = sum * 10 + ch - '0';
		if (sum >= phi)
		{
			sum %= phi;
			flag = true;
		}
	}
	
	if (flag)    sum += phi;
	
	return sum;
}

// 快速幂 
int qpow(int x, int n, int m)
{
	ll res = 1;
	while (n > 0)
	{
		if (n & 1)
			res = res * x % m;
		x = (ll)x * x % m;
		n >>= 1;
	}
	return res;
}

int main()
{
	#ifdef LOCAL
	freopen("test.in", "r", stdin);
	#endif
	
	cin >> a >> m >> b;
	int phi = get_phi(m);
	int n = depow(phi);
	cout << qpow(a, n, m) << endl;
	
	return 0;
}

posted @ 2024-05-21 19:48  ltign  阅读(1)  评论(0编辑  收藏  举报