题目大意:有N个数字,然后给你q个区间,要你求每一个区间中所有的数字从左到右依次垒起来的次方的幂对m取模之后的数字是多少。
用到一个新知识,欧拉降幂定理
记住公式 nx≡nφ(m) + x mod φ(m)(mod m)这个式子当且仅当x>φ(m)时满足。那么就可以递归求解了。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <map>
using namespace std;
int n;
long long m;
long long a[100005];
int q;
map<long long, long long> mp;
long long phi(long long x)
{
long long xx=x;
if(mp[x]!=0)
return mp[x];
long long ans=x;
for(long long i=2;i*i<=x;i++)
{
if(x%i==0)
{
ans=ans/i*(i-1);
while(x%i==0)
x/=i;
}
}
if(x!=1)
ans=ans/x*(x-1);
return mp[xx]=ans;
}
long long MOD(long long a,long long b)
{
if(a<b)
return a;
else
return (a%b)+b;
}
long long powd(long long a,long long b,long long mod)
{
long long ans=1;
while(b>0)
{
if(b%2==1)
ans=MOD(ans*a,mod);
a=MOD(a*a,mod);
b/=2;
}
return ans;
}
long long solve(int l,int r,long long mod)
{
if(l==r || mod==1)
{
return MOD(a[l],mod);
}
else
{
return powd(a[l],solve(l+1,r,phi(mod)),mod);
}
}
int main() {
while(~scanf("%d%lld",&n,&m))
{
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
scanf("%d",&q);
while(q--)
{
int l,r;
scanf("%d%d",&l,&r);
long long ans=solve(l,r,m);
printf("%lld\n",ans%m);
}
}
return 0;
}