题意
给定n个数,q次询问,每次输出[l,r]区间的超级幂,对m取模。
思路
超级幂问题就想到用欧拉降幂来处理
欧拉降幂公式:$a^b \% m=a^{b\%\varphi (m)+\varphi(m)}\%m,(b>\varphi(m))$
本题用递归处理欧拉降幂,在$logm$次降幂后$\varphi(m)=1$,然后回溯时用快速幂进行计算,总的复杂度大约是$log^{2}m$
$w_0^{w_1^{w_2^{w_3^{...}}}}\% m = w_0^{[w_1^{w_2^{w_3^{...}}}\%\varphi(m)+\varphi(m)]}\%m$
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+7; 4 map<int,int> euler; 5 long long w[maxn]; 6 int phi(int n) 7 { 8 int now=n; 9 int ret=n; 10 if(euler.count(now)) return euler[now];//记忆化 11 for(int i=2;i<=sqrt(n);i++) 12 { 13 if(n%i==0) 14 { 15 ret=ret/i*(i-1); 16 while(n%i==0) 17 n/=i; 18 } 19 } 20 if(n>1) 21 ret=ret/n*(n-1); 22 euler[now]=ret; 23 return ret; 24 } 25 long long MOD(long long n,int mod)//符合欧拉降幂规则的取模 26 { 27 return n<mod?n:(n%mod+mod); 28 } 29 long long quick_mod(long long base,long long p,int mod) 30 { 31 long long ret=1; 32 do{ 33 if(p&1) 34 ret=MOD(base*ret,mod); 35 base=MOD(base*base,mod); 36 }while(p>>=1); 37 return ret; 38 } 39 long long solve(int l,int r,int mod) 40 { 41 if(l==r||mod==1) return MOD(w[l],mod); 42 return quick_mod(w[l],solve(l+1,r,phi(mod)),mod); 43 } 44 int main() 45 { 46 int n,mod; 47 scanf("%d%d",&n,&mod); 48 for(int i=1;i<=n;i++) 49 scanf("%lld",&w[i]); 50 int q; 51 scanf("%d",&q); 52 while(q--) 53 { 54 int l,r; 55 scanf("%d%d",&l,&r); 56 long long ans=solve(l,r,mod)%mod; 57 printf("%lld\n",ans); 58 } 59 }
原文地址:https://www.cnblogs.com/computer-luo/p/9895653.html
时间: 2024-11-08 09:57:47