欧拉降幂

欧拉降幂

定理

  • a a a p p p 互质时, a b ≡ a b % φ ( p ) ( m o d    p ) a^b\equiv a^{b\%\varphi(p)} (\mod p) abab%φ(p)(modp)
  • b < φ ( p ) b<\varphi(p) b<φ(p) 时, a b ≡ a b % φ ( p ) ( m o d    p ) a^b\equiv a^{b\%\varphi(p)} (\mod p) abab%φ(p)(modp)
  • b ≥ φ ( p ) b \ge \varphi(p) bφ(p) 时, a b ≡ a b % φ ( p ) + φ ( p ) ( m o d    p ) a^b\equiv a^{b\%\varphi(p)+\varphi(p)} (\mod p) abab%φ(p)+φ(p)(modp)

细节:每次递归过程中维护的是指数,因此需要在 dfs 出口计算当前的指数,在 qpow 的过程中也通过指数的方式计算

bzoj3884. 上帝与集合的正确用法

链接:https://darkbzoj.tk/problem/3884

题意:给定一个 p ,求 2 2 ⋯ 2 2^{2^{\cdots^2}} 222 % p ( 1 ≤ p ≤ 1 0 7 ) (1\le p \le 10^7) 1p107

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+10;
int phi(int n)
{
    int res=n,a=n;
    for(int i=2; i*i<=a; ++i)
    {
        if(a%i==0)
        {
            res=res/i*(i-1);
            while(a%i==0) a/=i;
        }
    }
    if(a>1) res=res/a*(a-1);
    return res;
}
int t,p;
int mul(ll x,int mod)
{
    return x<mod?x:x%mod+mod;
}
int qpow(int b,int n,int mod)
{
    int res=1;
    while(n)
    {
        if(n&1) res=mul(1ll*res*b,mod);
        b=mul(1ll*b*b,mod);
        n>>=1;
    }
    return res;
}
int dfs(int x,int mod)
{
    if(mod==1) return 1;
    return qpow(2,dfs(x,phi(mod)),mod);
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&p);
        printf("%d\n",dfs(2,p)%p);
    }
    return 0;
}

2019ICPC南昌预选赛网络赛 B. super_log

链接:https://nanti.jisuanke.com/t/41299

题意:求解 a a … a a^{a^{\dots^a}} aaa % m的值

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+10;
int t,a,b,m;
int phi(int n)
{
    int res=n,a=n;
    for(int i=2; i*i<=a; ++i)
    {
        if(a%i==0)
        {
            res=res/i*(i-1);
            while(a%i==0) a/=i;
        }
    }
    if(a>1) res=res/a*(a-1);
    return res;
}

int mul(ll x,int mod)
{
    return x<mod?x:x%mod+mod;
}
int qpow(int b,int n,int mod)
{
    int res=1;
    while(n)
    {
        if(n&1) res=mul(1ll*res*b,mod);
        b=mul(1ll*b*b,mod);
        n>>=1;
    }
    return res;
}
int dfs(int a,int b,int mod)
{
	if(b==0) return 1;
    if(mod==1) return 1;
    return qpow(a,dfs(a,b-1,phi(mod)),mod);
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&a,&b,&m);
        printf("%d\n",dfs(a,b,m)%m);
    }
    return 0;
}

CF906D. Power Tower

链接:https://codeforces.com/contest/906/problem/D

题意:给定a的数组,每次询问给出l,r的值,求解 a [ l ] a [ l + 1 ] … a [ r − 1 ] a [ r ] a[l]^{a[l+1]^{\dots^{a[r-1]^{a[r]}}}} a[l]a[l+1]a[r1]a[r]%m

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+10;
int n,m,q,w[maxn];
unordered_map<int,int> mphi;
int phi(int n)
{
    if(mphi[n]) return mphi[n];
    int res=n,a=n;
    for(int i=2; i*i<=a; ++i)
    {
        if(a%i==0)
        {
            res=res/i*(i-1);
            while(a%i==0) a/=i;
        }
    }
    if(a>1) res=res/a*(a-1);
    return mphi[n]=res;
}
int mul(ll x,int mod)
{
    return x<mod?x:x%mod+mod;
}
int qpow(int b,int n,int mod)
{
    int res=1;
    while(n)
    {
        if(n&1) res=mul(1ll*res*b,mod);
        b=mul(1ll*b*b,mod);
        n>>=1;
    }
    return res;
}
int dfs(int l,int r,int mod)
{
    if(l==r) return mul(w[l],mod);
    if(mod==1) return 1;
    return qpow(w[l],dfs(l+1,r,phi(mod)),mod);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; ++i) scanf("%d",&w[i]);
    scanf("%d",&q);
    while(q--)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        printf("%d\n",dfs(l,r,m)%m);
    }
    return 0;
}