扩展欧拉定理:
有正整数a,b 有 正 整 数 a , b
ab=ab(mod p)(b<ϕ(p)) a b = a b ( m o d p ) ( b < ϕ ( p ) )
ab=ab mod ϕ(p)+ϕ(p)(mod p)(b>=ϕ(p)) a b = a b m o d ϕ ( p ) + ϕ ( p ) ( m o d p ) ( b >= ϕ ( p ) )
phi一直迭代下去log次就变成1了,这个易证。
所以这题是个结论题。
Code:
#include
#include
#define ll long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;
const int N = 100000;
int bz[N + 5], p[N];
void Built() {
fo(i, 2, N) {
if(!bz[i]) p[++ p[0]] = i;
fo(j, 1, p[0]) {
if(i * p[j] > N) break;
bz[i * p[j]] = 1;
if(!(i % p[j])) break;
}
}
}
int qphi(int x) {
int s = x;
for(int i = 1; p[i] * p[i] <= x; i ++)
if(x % p[i] == 0) {
s = s / p[i] * (p[i] - 1);
while(x % p[i] == 0) x /= p[i];
}
if(x > 1) s = s / x * (x - 1);
return s;
}
int n, m, m0, a[N + 5], Q, l, r, d[N];
int dg(int l, int r, int u) {
if(l > r) return 1;
if(u > d[0]) return 1;
if(l == r) return a[l] >= d[u] ? (a[l] % d[u] + d[u]) : a[l];
int y = dg(l + 1, r, u + 1);
int b1 = 0, b2 = 0; ll s = 1, x = a[l], mo = d[u];
while(y) {
if(y & 1) {
b1 |= (s * x >= mo) | b2;
s = s * x % mo;
}
y /= 2;
b2 |= x * x >= mo;
x = x * x % mo;
}
return (b1) ? s + mo : s;
}
int main() {
freopen("power.in", "r", stdin);
freopen("power.out", "w", stdout);
Built();
scanf("%d %d", &n, &m); m0 = m;
while(m > 1) {
m = qphi(m);
d[++ d[0]] = m;
}
fo(i, 1, n) scanf("%d", &a[i]);
for(scanf("%d", &Q); Q; Q --) {
scanf("%d %d", &l, &r);
ll y = dg(l + 1, r, 1);
ll x = a[l], s = 1, mo = m0;
while(y) {
if(y & 1) s = s * x % mo;
y /= 2; x = x * x % mo;
}
printf("%lld\n", s);
}
}