Power Tower
题目大意:有N个数字,然后给你q个区间,要你求每一个区间中所有的数字从左到右依次垒起来的次方的幂对m取模之后的数字是多少。
用到一个新知识,欧拉降幂定理
记住公式 $LARGE n^x equiv n^{varphi(m) + x mod varphi(m)}(mod m)$这个式子当且仅当x>φ(m)时满足。那么就可以递归求解了。
暂时不太明白怎么证明
#include<iostream> #include<cstdio> #include<cstring> #include<map> #define maxn 100010 #define Mod(a,b) a<b?a:a%b+b using namespace std; long long n,m,a[maxn]; map<long long,long long>p; long long qread(){ long long i=0,j=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')j=-1;ch=getchar();} while(ch<='9'&&ch>='0')i=i*10+ch-'0',ch=getchar(); return i*j; } long long Pow(long long x,long long y,long long mod){ long long res=1; while(y){ if(y&1)res=Mod(res*x,mod); x=Mod(x*x,mod); y>>=1; } return res; } long long phi(long long k){ long long s=k,x=k; if(p[k])return p[k]; for(long long i=2;i*i<=k;i++){ if(k%i==0)s=s/i*(i-1); while(k%i==0)k/=i; } if(k>1)s=s/k*(k-1); p[x]=s;return s; } long long solve(int l,int r,long long mod){ if(l==r||mod==1)return Mod(a[l],mod); return Pow(a[l],solve(l+1,r,phi(mod)),mod); } int main(){ freopen("Cola.txt","r",stdin); n=qread();m=qread(); for(int i=1;i<=n;i++)a[i]=qread(); int Q;scanf("%d",&Q); int l,r; while(Q--){ scanf("%d%d",&l,&r); cout<<solve(l,r,m)%m<<endl; } return 0; }