1. 程式人生 > 其它 >#擴充套件尤拉定理#CF906D Power Tower

#擴充套件尤拉定理#CF906D Power Tower

擴充套件尤拉定理

題目

給定一個數列,有\(m\)組詢問
定義

\[\large f(x-1)={a_x}^{f(x)} \]

\(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;
}