给定数组w,q次查询,求w[ql]^ ( w[ql + 1] ^ ( ... w[qr - 1] ^ (w[qr]) ) ) % m
扩展欧拉定理 (a,m) != 1时,
if(b >= phi(m)) a^b % m = a ^ (b % phi(m) + phi(m) ) % m
if(b < phi(m)) a^b % m = a ^ b % m(快速幂)
1.快速幂和递归时要时刻注意指数和phi(m)的大小关系
ll qk_pow(ll a,ll b,ll p)
{
ll ans = 1;
a = a >= p ? a % p + p : a;
while (b) {
if(b & 1) ans = ans * a >= p ? ans * a % p + p : ans * a % p;
b >>= 1;
a = a * a >= p ? a * a % p + p : a * a % p;
}
return ans;
}
2.
ll f(int ql,int qr,int pos)
{
int m = v[pos];
if(m == 1) return 1;
if(ql == qr) return w[ql] < m ? w[ql] : w[ql] % m + m;
ll x = f(ql + 1,qr,pos + 1);
ll ans = qk_pow(w[ql], x , m);
return ans;
}
#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
int n,m;
int w[maxn];
vector<int> v;
int phi(int m)
{
int ans = m;
for (int i = 2; i <= sqrt(0.5 + m); i ++) {
if(m % i == 0){
ans = ans / i * (i - 1);
while(m % i == 0 ) m /= i;
}
}
if(m > 1) ans = ans / m * (m - 1);
return ans;
}
void init(int m)
{
v.clear();
//预处理phi(m)
int x = m;
v.push_back(x);
while (1) {
x = phi(x);
v.push_back(x);
if(x == 1) break;
}
}
ll qk_pow(ll a,ll b,ll p)
{
ll ans = 1;
a = a >= p ? a % p + p : a;
while (b) {
if(b & 1) ans = ans * a >= p ? ans * a % p + p : ans * a % p;
b >>= 1;
a = a * a >= p ? a * a % p + p : a * a % p;
}
return ans;
}
ll f(int ql,int qr,int pos)
{
int m = v[pos];
if(m == 1) return 1;
if(ql == qr) return w[ql] < m ? w[ql] : w[ql] % m + m;
ll x = f(ql + 1,qr,pos + 1);
ll ans = qk_pow(w[ql], x , m);
return ans;
}
int main()
{
while (scanf("%d%d",&n,&m) != EOF) {
init(m);
for (int i = 1; i <= n; i ++) {
scanf("%d",&w[i]);
}
int q;scanf("%d",&q);
int ql,qr;
ll ans;
while (q --) {
scanf("%d%d",&ql,&qr);
ans = f(ql,qr,0);
ans = (ans + m) % m;
printf("%I64d\n",ans);
}
}
return 0;
}