CF906D Power Tower
感觉没啥好说的,只要你知道扩展欧拉定理的式子就很 trivial 的一个题
幂塔类的问题都考虑用扩展欧拉定理降幂,则每往指数上操作一层复杂度模数就会从 \(m\) 变为 \(\phi(m)\)
根据经典结论可知,该过程在大约 \(\log m\) 次操作后就会让模数变为 \(1\),此时后面的部分就无需再计算了
不过要注意在使用扩展欧拉定理时需要对快速幂略作修改,当求出的结果 \(t\ge \phi(m)\) 时要变为 \(t\bmod \phi(m)+\phi(m)\)
总复杂度 \(O(q\log^2 m)\)
#include<cstdio>
#include<iostream>
#include<map>
#define RI register int
#define CI const int&
using namespace std;
const int N=100005;
int n,mod,a[N],q,l,r; map <int,int> phi;
inline int get_phi(int n)
{
if (n==1) return 1;
if (phi.count(n)) return phi[n];
int tmp=n,ret=n;
for (RI i=2;i*i<=n;++i)
if (n%i==0)
{
ret=ret/i*(i-1);
while (n%i==0) n/=i;
}
if (n>1) ret=ret/n*(n-1);
return phi[tmp]=ret;
}
inline int quick_pow(int x,int p,int mod,int mul=1)
{
for (;p;p>>=1)
{
if (p&1)
{
if (1LL*mul*x>=mod) mul=1LL*mul*x%mod+mod; else mul=1LL*mul*x;
}
if (1LL*x*x>=mod) x=1LL*x*x%mod+mod; else x=1LL*x*x;
}
return mul;
}
inline int solve(CI l,CI r,CI mod)
{
if (l>r||mod==1) return 1;
int p=solve(l+1,r,get_phi(mod));
return quick_pow(a[l],p,mod);
}
int main()
{
RI i; for (scanf("%d%d",&n,&mod),i=1;i<=n;++i) scanf("%d",&a[i]);
for (scanf("%d",&q);q;--q)
scanf("%d%d",&l,&r),printf("%d\n",solve(l,r,mod)%mod);
return 0;
}
辣鸡老年选手AFO在即