到这里就可以看出,每迭代一遍欧拉函数,就相当于把 m 中的所有质因子全部取出来减个一再乘回去,要得到 ϕ(m)=1,只需要迭代 m 中每个质因子可以取出来的2的数量,时间复杂度是 log 级的
对于题目中的每一个 ϕ 可以先预处理一遍,用 map 存起来
代码
#include<iostream> #include<cstdio> #include<unordered_map> using namespace std; const int N = 1e5 + 5; typedef long long ll;
unordered_map<ll, ll> phi; ll w[N];
ll pi(ll p) { ll res = p; for (ll i = 2; i * i <= p; i++) { if (p % i == 0) res -= res / i; while (p % i == 0) p /= i; } if (p > 1) res -= res / p; return res; }
ll qmi(ll a, ll b, ll c) { ll res = 1; bool flag = false; while (b) { if (b & 1) { res *= a; if (res >= c) flag = true; res %= c; } a *= a; if (a >= c) flag = true; a %= c; b >>= 1; } if (flag) res += c;//需要满足欧拉定理 return res; }
ll dfs(ll l, ll r, ll p) { if (l == r + 1 || p == 1) return 1; return qmi(w[l], dfs(l + 1, r, phi[p]), p); }
int main() { ll n, p; scanf("%lld%lld", &n, &p); for (ll i = 1; i <= n; i++) scanf("%lld", &w[i]); ll now = p; while (now != 1) phi[now] = pi(now), now = phi[now]; phi[now] = 1; ll q; scanf("%lld", &q); while (q--) { ll l, r; scanf("%lld%lld", &l, &r); printf("%lld\n", dfs(l, r, p) % p); } return 0; }