题目来源:https://codeforces.com/contest/906/problem/D
题意很简单,求次幂取模的值。
顺便每次判断一下比方说a^b%p,判断b与phi(p)的大小关系,
暴力判断的话就取log判断大小,大佬们总是有办法去化简,加入了一个
ll MOD(ll n,ll mod)
{
return n<mod?n:(n%mod+mod);
}
巧妙避开了判断,这就是在比较b和phi(p)的大小。
其实也就是
证明可看:https://www.cnblogs.com/ACMLCZH/p/8117161.html
记得用map记忆化存储之前计算过的euler。
一开始想着把1e7的打个表,大于的再去计算,果然没卡过去.......。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<vector>
#include<algorithm>
#include<map>
#include<queue>
#define MAX_len 50100*4
using namespace std;
typedef long long ll;
const ll MAX=1e7;
map<ll,ll>euler;
ll phi[MAX],a[100100];
ll MOD(ll n,ll mod)
{
return n<mod?n:(n%mod+mod);
}
void Euler()
{
phi[1]=1;
for(ll i=2;i<MAX;i++)
phi[i]=i;
for(ll i=2;i<MAX;i++)
if(phi[i]==i)
for(ll j=i;j<MAX;j+=i)
phi[j]=phi[j]/i*(i-1);
}
ll quickpow(ll a,ll n,ll mod)
{
ll res=1;
a=MOD(a,mod);
while(n)
{
if(n&1)
{
res=MOD(a*res,mod);
}
n>>=1;
a=MOD(a*a,mod);
}
return res;
}
ll euler1(ll n)
{
ll now=n;
ll ret=n;
if(euler.count(now)) return euler[now];
for(ll i=2;i<=sqrt(n);i++)
{
if(n%i==0)
{
ret=ret/i*(i-1);
while(n%i==0)
n/=i;
}
}
if(n>1)
ret=ret/n*(n-1);
euler[now]=ret;
return ret;
}
ll solve(ll l,ll r,ll mod)
{
if(l==r||mod==1)
return MOD(a[l],mod);
{
return quickpow(a[l],solve(l+1,r,euler1(mod)),mod);
}
}
int main()
{
// Euler();
ll n,i,j,mod;
scanf("%I64d %I64d",&n,&mod);
for(i=1;i<=n;i++)
{
scanf("%I64d",&a[i]);
}
int q;
scanf("%d",&q);
while(q--)
{
ll l,r,d,b;
scanf("%I64d %I64d",&l,&r);
{
ll as=solve(l,r,mod)%mod;
printf("%I64d\n",as);
}
}
return 0;
}
扫描二维码关注公众号,回复:
8780092 查看本文章