# 【NOI2018模拟4.7】power（扩展欧拉定理）

### 题解：

#### 必要定理：

$有正整数a,b$$有正整数a,b$
$a^b=a^b(mod~p)(b<\phi(p))$
$a^b=a^{b~mod~\phi(p)+\phi(p)}(mod~p)(b>=\phi(p))$

phi一直迭代下去log次就变成1了，这个易证。

Code：

#include<cstdio>
#include<cstring>
#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);
}
}

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120