欧拉降幂算法

欧拉降幂

说明

在之前的文章中提到过快速幂及其取余的运算

快速幂及其模 - 菜缤的世界 CairBin’s Blog

但是有时候对于 a n   m o d   m a^{n}\space mod\space m an mod m,n会非常大,这时候我们可能需要用欧拉降幂的方法来处理

正文

原理

欧拉降幂公式如下
a n   m o d   m = a n   m o d   φ ( m ) + φ ( m )   m o d   m a^{n}\space mod \space m = a^{n\space mod \space \varphi (m)+\varphi (m)}\space mod \space m an mod m=an mod φ(m)+φ(m) mod m
其中 φ ( m ) \varphi (m) φ(m) 为欧拉函数

代码

知道公式后,显然需要抽象几个函数出来

  • 快速幂取模
//ll 指 long long int,这里用了个typedef
ll quick_pow_mod(ll a, ll b, ll m)
{
    
    
	ll res = 1;
	a %= m;
	while (b) {
    
    
		if (b & 1) res = (res * a) % m;
		a = (a * a) % m;
		b >>= 1;
	}
	return res;
}
  • 欧拉函数
ll euler_func(ll x) {
    
    
	ll e_num = x;
	for (ll i = 2; i * i <= x; i++)
	{
    
    
		if (x % i == 0)
		{
    
    
			e_num = e_num / i * (i - 1);
			while (x % i == 0)
				x /= i;
		}
	}

	if (x > 1)
		e_num = e_num / x * (x - 1);

	return e_num;
}

利用上面两个函数,可写出欧拉降幂

/*
	欧拉降幂
	a为底数
	n为次幂,这里用字符串存
	m为取模数
*/
ll euler_drop_pow(ll a, string n, ll m)
{
    
    
	ll e_num = euler_func(m);
	ll des_power = 0;
	bool flag = false;
	for (ll i = 0; i < n.size(); i++)
	{
    
    
		des_power = (des_power * 10 + n[i] - 48) % e_num;
		if (des_power > e_num)
		{
    
    
			flag = true;
			des_power %= e_num;
		}
	}

	if(flag)
		des_power += e_num;

	return quick_pow_mod(a, des_power, m);
}

相关习题

  • 洛谷P5091

猜你喜欢

转载自blog.csdn.net/qq_42759112/article/details/129543918