2019南京网络赛B. super_log--欧拉降幂

我对欧拉降幂的理解(19.4.6)

原题CodeForces 906D Power Tower  有限幂塔函数模板(此题参考)

BZOJ    3884                                         无限次模板

 

一.题意及分析

 

题意:

求log*a(x)>=b,最小x

 

分析:

 

可以看出是单调递增,显然取等号,x最小

观察可知,x>=1,不断递归下去,左边每次递归累加1,右边log*a(F(x))中F(x)不断取log,最终x=a时,F(x)=0,此时log*a=-1,加上左边的1,正好抵消,所以共递归了b次(不包含最后一次),最后左边累加的结果刚好就是b

因此实际求一个幂塔函数

x = a^a^a^.........^a^a(一共b个a的高阶幂)%m;

 

于是用欧拉降幂:(分析见上面,有限个幂塔函数模板题链接)

但注意特判a,b,mod=0 or 1

 

二.代码

#include<bits/stdc++.h>
#define Mod(a,b) a<b?a:a%b+b						//重定义取模,按照欧拉定理的条件
#define LL long long
#define N 100010
using namespace std;
 
LL n,q,mod,a;
map<LL,LL> mp;
 
LL qpow(LL x,LL n,LL mod)
{
    LL res=1;
    while(n)
    {
        if (n&1) res=Mod(res*x,mod),n--;
        x=Mod(x*x,mod); n>>=1;
    }
    return res;
}
 
LL phi(LL k)
{
    LL i,s=k,x=k;
    if (mp.count(k)) return mp[x];					//记忆化存储
    for(i = 2;i * i <= k; i++)
    {
        if(k % i == 0) s = s / i * (i - 1);
        while(k % i == 0) k /= i;
    }
    if(k > 1) s = s / k * (k - 1);
    mp[x]=s; return s;
}
 
LL solve(LL l,LL r,LL mod)
{
    if (l==r||mod==1) return Mod(a,mod);					//如果到右端点或者φ值等于1,那么直接返回当前数字
    return qpow(a,solve(l+1,r,phi(mod)),mod);			//否则指数为[l+1,r]区间的结果
}
 
int main()
{
    //scanf("%lld%lld",&n,&mod);
   // for(int i=1;i<=n;i++)
        //scanf("%lld",&a[i]);
    scanf("%lld",&q);
    while(q--)
    {
        LL L,R;
        scanf("%lld%lld%lld",&a,&R,&mod);
        if(mod == 1)//两句特判必不可少,不然WA
            printf("0\n");
        else if(R== 0 || a == 1)
            printf("1\n");
        else
        printf("%lld\n",solve(1,R,mod)%mod);				
//对mod取模,因为qpow内部是用Mod(a,b)取模
    }
    return 0;
}
 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值