【CF906D】Power Tower

题目

题目链接: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;
}
posted @ 2020-03-31 13:29  stoorz  阅读(...)  评论(...编辑  收藏