习题:Power Tower(欧拉定理)

题目

传送门

思路

首先我们考虑暴力的做法

也就是说我们直接用欧拉定理直接暴力做

时间复杂度为\(O(n*m)\)

这个时间复杂度明显是原地爆炸的

但是我们考虑在用欧拉函数的过程中

每一层都会使用到上一层的\(\varphi\)

单独考虑\(\varphi\)的变化过程,很容易发现

\(\varphi(\varphi(m))\le \frac{\varphi(m)}{2}\)

而且 \(\varphi(1)=1\)

我们考虑1个数与取模1再加1,

这不还是1么

所以这样下来总的时间复杂度可以降到\(O(m*log_n)\)

代码

#include<iostream>
using namespace std;
long long n,mod;
long long m;
long long l,r;
long long a[500005];
long long phi[500005];
long long varphi(long long n)
{
	long long ans=n;
	for(int i=2;1ll*i*i<=n;i++)
	{
		if(n%i==0)
		{
			ans=ans/i*(i-1);
			while(!(n%i))
			{
				n/=i;
			}
		}
	}
	if(n>1)
		ans=ans/n*(n-1);
	return ans;
}
long long ex_oular(long long x,long long mod)
{
	if(x>=mod)
		return x=x%mod+mod;
	else
		return x;
}
long long qkpow(long long a,long long b,long long mod)
{
	if(b==0)
		return 1;
	if(b==1)
		return a;
	long long t=qkpow(a,b/2,mod);
	t=ex_oular(t*t,mod);
	if(b%2==1)
		t=ex_oular(t*a,mod);
	return t;
}
long long dfs(long long l,long long r,long long k)
{
	if(l==r||phi[k]==1)
	{
		return ex_oular(a[l],phi[k]);
	}
	return qkpow(a[l],dfs(l+1,r,k+1),phi[k]);
}
int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>mod;
	phi[0]=mod;
	for(int i=1;i<=n;i++)
		phi[i]=varphi(phi[i-1]);
	for(int i=1;i<=n;i++)
		cin>>a[i];
	cin>>m;
	for(int i=1;i<=m;i++)
	{
		cin>>l>>r;
		cout<<dfs(l,r,0)%mod<<'\n';
	}
	return 0;
}
posted @ 2019-11-24 15:18  loney_s  阅读(302)  评论(0)    收藏  举报