计蒜客 Exponial (欧拉降幂)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_41156591/article/details/79936030

题目链接

题意:给出一个n(1~1e9),m(1~1e9),求exponial(n)%m的值

解法:有这样一个欧拉降幂的公式

         \left\{\begin{matrix} A^{B}mod (C)=A^{Bmod(phi(C))}modC& (B<phi(C)) \\ A^{B}mod (C)=A^{Bmod(phi(C))+phi(C)}modC& (B>=phi(C)) \end{matrix}\right.

          (phi(x)表示x的欧拉值)

          从n向1来DFS,在中间求幂时使用快速幂取膜然后就可以算出答案了~

欧拉函数:

                      对一个正整数N,欧拉函数是小于N且与N互质的数的个数.。

                      例如φ(24)=8,因为1, 5, 7, 11, 13, 17, 19, 23均和 24 互质。

                      φ(n) = n*(1-\frac{1}{p1})*(1-\frac{1}{p2})*....*(1-\frac{1}{pn})  其中(p1.....pn)为N的素因子.

                       φ(24)=24*(1-\frac{1}{2})*(1-\frac{1}{3})=8.

代码如下

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
const int maxn = 1e5 + 500;
#define inf 0x3f3f3f3f
#define ll long long
ll biao[] = { 0,1,2,9,(1 << 18) };//题目给出的式子的n<=4的结果值
ll mod_pow(ll a, ll n, ll mod) {//快速幂
	a %= mod;
	ll ret = 1;
	while (n) {
		if (n & 1) ret = (ret*a) % mod;
		a = a*a%mod;
		n >>= 1;
	}
	return ret;
}
ll euler(ll n) { //log(n)时间内求一个数的欧拉值
	ll ans = n;
	for (ll i = 2; i*i <= n; i++) {
		if (n%i == 0)
		{
			ans -= ans / i;
			while (n%i == 0) n /= i;
		}
	}
	if (n>1) ans -= ans / n;
	return ans;
}
ll dfs(ll n, ll m) {
	if (m == 1) return 1;
	if (n <= 4)    //因为当n<=4时才有可能出现幂小于等于模数的情况,其余时候都是幂大于模数
	{              //所以预处理出n的最小4项结果,第5项已经远大于模数的最大值1e9了
		if (biao[n] >= m) return biao[n] % m + m;
		return biao[n];
	}
	ll exp = dfs(n - 1, euler(m));
	return mod_pow(n, exp, m) + m;
}
int main() {
	ll n, mod;
	while (~scanf("%lld%lld", &n, &mod)) {
		ll exp = dfs(n - 1, euler(mod));
		ll ans = mod_pow(n, exp, mod);
		printf("%lld\n", ans);
	}
}

 

 

 

阅读更多

没有更多推荐了,返回首页