欧拉降幂公式

今天补了一题codeforces 907 的 F 题,看了题解才知道有这个东西(欧拉降幂公式)

我觉我要说的都在代码里了,如果还有啥不理解的,可以看看大佬的博客:https://www.cnblogs.com/ACMLCZH/p/8117161.html

#include<bits/stdc++.h>
#define de(x) cout<<#x<<"="<<x<<endl;
#define dd(x) cout<<#x<<"="<<x<<" ";
#define rep(i,a,b) for(int i=a;i<(b);++i)
#define repd(i,a,b) for(int i=a;i>=(b);--i)
#define mt(a,b) memset(a,b,sizeof(a))
#define fi first
#define se second
#define inf 0x7f
#define pii pair<int,int>
#define pdd pair<double,double>
#define pdi pair<double,int>
#define mp(u,v) make_pair(u,v)
#define sz(a) a.size()
#define ull unsigned long long
#define ll long long
#define pb push_back
#define PI acos(-1.0)
const int maxn = 1e5+5;
const double EPS = 1e-6;
using namespace std;
map<ll,ll> mp;
ll a[maxn];
int mod(ll x,int p){//欧拉降幂公式的取模方法 
    return x>=p?x%p+p:x; 
}
ll kpow(ll a,ll b,ll p){ //符合欧拉降幂公式的快速幂 
    ll ret = 1;
    while(b){
        if(b&1) ret = mod(ret*a,p); 
        b >>= 1;
        a = mod(a*a,p); 
    }
    return ret;
}
ll phi(ll k){//求解欧拉函数(他的意思就是比k小且和k互质的数字的个数) 
    ll s=k,kk=k;
    if(mp.count(k)) return mp[k];
    for(ll 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);
    return mp[kk]=s;
}
ll solve(int l,int r,ll p){ //递归求解,最多logp次,因为phi(p)最慢的话就是log次能到1,那么到一的话,就直接可以返回a[l]%p+p,因为任何数字mod 1都是零 
    if( l == r || p  == 1 ) return mod(a[l],p); 
    return kpow(a[l],solve(l+1,r,phi(p)),p); 
}
int main()
{
    int n,q;
    ll p;
    scanf("%d%lld",&n,&p);
    rep(i,1,n+1) scanf("%lld",&a[i]);
    scanf("%d",&q);
    int l,r;
    rep(i,0,q){
        scanf("%d%d",&l,&r);
        printf("%lld
",solve(l,r,p)%p);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/chinacwj/p/8150654.html