码迷,mamicode.com
首页 > 其他好文 > 详细

【CF906D】Power Tower

时间:2020-03-31 14:40:30      阅读:53      评论:0      收藏:0      [点我收藏+]

标签:优化   时间   while   ons   一个   problem   pre   https   ima   

题目

题目链接: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;
}

【CF906D】Power Tower

标签:优化   时间   while   ons   一个   problem   pre   https   ima   

原文地址:https://www.cnblogs.com/stoorz/p/12604597.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!