#擴充套件尤拉定理#CF906D Power Tower
阿新 • • 發佈:2021-08-11
擴充套件尤拉定理
注意一旦\(x\geq \varphi(p)\)一定要補上\(a^{\varphi(p)}\)才能保證正確性
題目
給定一個數列,有\(m\)組詢問
定義
若 \(f(r)=a_r\) 求 \(f(l)\)
對固定的 \(mod\) 取模
分析
根據擴充套件尤拉定理
\[\large \begin{cases} a^x\equiv a^{x\bmod \varphi(p)+\varphi(p)}\pmod p,x\geq \varphi(p)\\ a^x,otherwise \end{cases} \]一次\(\varphi(p)\)至少會將下一層的模數縮小一半(\(p>2\))
那麼最多\(\log p\)次就會結束遞迴,那麼時間複雜度為\(O(m\log mod)\)
注意一旦\(x\geq \varphi(p)\)一定要補上\(a^{\varphi(p)}\)才能保證正確性
程式碼
#include <cstdio> #include <cctype> #include <map> #define rr register using namespace std; int n,mod,l,r,a[100011]; map<int,int>phi; inline signed iut(){ rr int ans=0; rr char c=getchar(); while (!isdigit(c)) c=getchar(); while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar(); return ans; } inline void print(int ans){ if (ans>9) print(ans/10); putchar(ans%10+48); } inline signed min(int a,int b){return a<b?a:b;} inline void Get_Phi(int &p){ rr int now=p,m=p; for (rr int i=2;i*i<=p;++i) if (p%i==0){ now=now/i*(i-1); while (p%i==0) p/=i; } if (p>1) now=now/p*(p-1); p=phi[m]=now; } inline signed ksm(int x,int y,int p){ rr long long ans=1,t; for (;y;y>>=1){ if (y&1){ t=ans*x; if (t>=p) t=t%p+p; ans=t; } t=1ll*x*x; if (t>=p) t=t%p+p; x=t; } return ans; } inline signed answ(int x,int p){ if (x==r+1||p==1) return 1; rr int mi=answ(x+1,phi[p]); return ksm(a[x],mi,p); } signed main(){ n=iut(),mod=iut(); for (rr int t=mod;t>1;Get_Phi(t)); for (rr int i=1;i<=n;++i) a[i]=iut(); for (rr int Q=iut();Q;--Q) l=iut(),r=iut(),print(answ(l,mod)%mod),putchar(10); return 0; }