Codeforces 906 Power Tower

题目来源: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)的大小。

其实也就是w0^{MOD(w1^{MOD(w2...))},phi(p)))}mod 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 查看本文章
发布了56 篇原创文章 · 获赞 17 · 访问量 2322

猜你喜欢

转载自blog.csdn.net/weixin_43958964/article/details/102229138