题目
题目链接:https://codeforces.com/problemset/problem/906/D
给出一个数列 \(a\),每次询问给出 \(l,r\),求
思路
根据扩展欧拉定理,当 \(b\geq \varphi(p)\) 时,
\[a^b\equiv a^{b\bmod \varphi(p)+\varphi(p)}\pmod p
\]
所以我们可以考虑递归求解,类似 这题,直到 \(l>r\) 或 \(p=1\)。
由于 \(\varphi(\varphi(n))...\) 在 \(\log n\) 次就会下降至 1,所以递归求解时间复杂度 \(O(n\log n)\)。
但是这题 \(p\leq 10^9\),线性筛显然不行,考虑到只有 \(O(n\log n)\) 个数要求 \(\varphi\),所以直接每个数暴力求 \(\varphi\),然后套上记忆化优化一下即可。
时间复杂度 \(O(n\sqrt{n}\log n)\)。而且远远跑不满。
代码
#include <map>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=100010;
int n,Q,MOD,a[N];
map<int,int> phi;
int Phi(int x)
{
if (phi[x]) return phi[x];
int p=x,y=x;
for (int i=2;i*i<=x;i++)
if (x%i==0)
{
p=p/i*(i-1);
while (x%i==0) x/=i;
}
if (x>1) p=p/x*(x-1);
return phi[y]=p;
}
ll fpow(ll x,ll k,int mod)
{
ll ans=1;
for (;k;k>>=1,x*=x)
{
if (x>=mod) x=x%mod+mod;
if (k&1) ans=ans*x;
if (ans>=mod) ans=ans%mod+mod;
}
return ans;
}
int solve(int x,int y,int p)
{
if (p==1 || x>y) return 1;
return (int)fpow(a[x],solve(x+1,y,Phi(p)),p);
}
int main()
{
scanf("%d%d",&n,&MOD);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
scanf("%d",&Q);
while (Q--)
{
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",solve(l,r,MOD)%MOD);
}
return 0;
}
原文地址:https://www.cnblogs.com/stoorz/p/12604597.html
时间: 2024-09-29 21:42:46