题目
给定一个数列,有(m)组询问
定义
[large f(x-1)={a_x}^{f(x)}
]
若 (f(r)=a_r) 求 (f(l))
对固定的 (mod) 取模
分析
根据扩展欧拉定理
[large
egin{cases}
a^xequiv a^{xmod varphi(p)+varphi(p)}pmod p,xgeq varphi(p)\
a^x,otherwise
end{cases}
]
一次(varphi(p))至少会将下一层的模数缩小一半((p>2))
那么最多(log p)次就会结束递归,那么时间复杂度为(O(mlog mod))
注意一旦(xgeq varphi(p))一定要补上(a^{varphi(p)})才能保证正确性
代码
#include <cstdio>
#include <cctype>
#include <map>
#define rr register
using namespace std;
int n,mod,l,r,a[100011];
map<int,int>phi;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline signed min(int a,int b){return a<b?a:b;}
inline void Get_Phi(int &p){
rr int now=p,m=p;
for (rr int i=2;i*i<=p;++i)
if (p%i==0){
now=now/i*(i-1);
while (p%i==0) p/=i;
}
if (p>1) now=now/p*(p-1);
p=phi[m]=now;
}
inline signed ksm(int x,int y,int p){
rr long long ans=1,t;
for (;y;y>>=1){
if (y&1){
t=ans*x;
if (t>=p) t=t%p+p;
ans=t;
}
t=1ll*x*x;
if (t>=p) t=t%p+p;
x=t;
}
return ans;
}
inline signed answ(int x,int p){
if (x==r+1||p==1) return 1;
rr int mi=answ(x+1,phi[p]);
return ksm(a[x],mi,p);
}
signed main(){
n=iut(),mod=iut();
for (rr int t=mod;t>1;Get_Phi(t));
for (rr int i=1;i<=n;++i) a[i]=iut();
for (rr int Q=iut();Q;--Q)
l=iut(),r=iut(),print(answ(l,mod)%mod),putchar(10);
return 0;
}