CodeForces 906D Power Tower <<欧拉降幂

题意

给定n个数,q次询问,每次输出[l,r]区间的超级幂,对m取模。

思路

超级幂问题就想到用欧拉降幂来处理

欧拉降幂公式:$a^b \% m=a^{b\%varphi (m)+varphi(m)}\%m,(b>varphi(m))$

本题用递归处理欧拉降幂,在$logm$次降幂后$varphi(m)=1$,然后回溯时用快速幂进行计算,总的复杂度大约是$log^{2}m$

$w_0^{w_1^{w_2^{w_3^{...}}}}\% m = w_0^{[w_1^{w_2^{w_3^{...}}}\%varphi(m)+varphi(m)]}\%m$

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e5+7;
 4 map<int,int> euler;
 5 long long w[maxn];
 6 int phi(int n)
 7 {
 8     int now=n;
 9     int ret=n;
10     if(euler.count(now)) return euler[now];//记忆化
11     for(int i=2;i<=sqrt(n);i++)
12     {
13         if(n%i==0)
14         {
15             ret=ret/i*(i-1);
16             while(n%i==0)
17                 n/=i;
18         }
19     }
20     if(n>1)
21         ret=ret/n*(n-1);
22     euler[now]=ret;
23     return ret;
24 }
25 long long MOD(long long n,int mod)//符合欧拉降幂规则的取模
26 {
27     return n<mod?n:(n%mod+mod);
28 }
29 long long quick_mod(long long base,long long p,int mod)
30 {
31     long long ret=1;
32     do{
33         if(p&1)
34             ret=MOD(base*ret,mod);
35         base=MOD(base*base,mod);
36     }while(p>>=1);
37     return ret;
38 }
39 long long solve(int l,int r,int mod)
40 {
41     if(l==r||mod==1) return MOD(w[l],mod);
42     return quick_mod(w[l],solve(l+1,r,phi(mod)),mod);
43 }
44 int main()
45 {
46     int n,mod;
47     scanf("%d%d",&n,&mod);
48     for(int i=1;i<=n;i++)
49         scanf("%lld",&w[i]);
50     int q;
51     scanf("%d",&q);
52     while(q--)
53     {
54         int l,r;
55         scanf("%d%d",&l,&r);
56         long long ans=solve(l,r,mod)%mod;
57         printf("%lld
",ans);
58     }
59 }
原文地址:https://www.cnblogs.com/computer-luo/p/9895653.html