Codeforces906 D. Power Tower(广义欧拉降幂+技巧)

本文介绍了一种在给定模数下,对于数组的区间查询进行优化的算法。通过递归处理和欧拉函数的应用,实现O(log)层级的计算,利用map存储预计算的欧拉函数值,避免重复计算,提高效率。文章详细解释了如何使用特制的取模函数简化降幂过程,避免了大数比较的复杂性。
摘要由CSDN通过智能技术生成
题意:

给定一个长度为n的数组w,模数m,
q组询问,每组询问给定l,r,要求计算:
在这里插入图片描述

数据范围:n,q<=1e5,m<=1e9,w(i)<=1e9

解法:

递归处理,虽然要求计算[L,R],但是模数phi[p]会不断变小,O(log)层就会变为1
因为m是1e9的,只能O(sqrt)计算phi,
但是因为只有O(log)层,也只需要记录O(log)个phi,开个map记录一下phi,避免每次计算phi都要O(sqrt)

降幂公式:
在这里插入图片描述

当不保证互质的时候,降幂过程需要比较b和phi[p]的大小然后分情况,但是b很大,不好比较,
可以将取模替换为:

int mo(long long x,int mod) {return x<mod?x:x%mod+mod;}

这是在比较b和phi[p]的大小,如果b<phi[p],返回b;否则返回b%phi[p]+phi[p]。
(其他地方看到的一个说法:保留一个phi[p]是为了保证取模之后仍然满足欧拉降幂的公式,防止把原本大于phi[p]的数取模之后变为小于phi[p])

将solve函数和快速幂函数中的取模都替换成这个,这样就不用分类讨论了
最后得到的答案需要加一个正常的%mod

code:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxm=1e5+5;
int a[maxm];
int n,m;
int mo(ll x,int mod){
    return x<mod?x:x%mod+mod;
}
int phi(int n){//单个数的欧拉函数值
    static unordered_map<int,int>p_mark;//开个map存,避免每次查询复杂度都是O(sqrt(n))
    if(p_mark.count(n))return p_mark[n];//如果map中有则直接返回
    int nn=n;
    int ans=n;
    for(int i=2;i*i<=n;i++){
        if(n%i==0){
            ans=ans/i*(i-1);
            while(n%i==0)n/=i;
        }
    }
    if(n>1)ans=ans/n*(n-1);
    return p_mark[nn]=ans;//记录到map中
}
int ppow(int a,int b,int mod){
    int ans=mo(1,mod);a=mo(a,mod);
    while(b){
        if(b&1)ans=mo(1LL*ans*a,mod);
        a=mo(1LL*a*a,mod);
        b>>=1;
    }
    return ans;
}
int solve(int l,int r,int m){
    if(m==1)return mo(a[l],m);
    if(l==r)return mo(a[l],m);
    return ppow(a[l],solve(l+1,r,phi(m)),m);
}
signed main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    int q;scanf("%d",&q);
    while(q--){
        int l,r;scanf("%d%d",&l,&r);
        int ans=solve(l,r,m)%m;
        printf("%d\n",ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值