欧拉降幂
欧拉降幂
定理:
- 当 a a a 、 p p p 互质时, a b ≡ a b % φ ( p ) ( m o d p ) a^b\equiv a^{b\%\varphi(p)} (\mod p) ab≡ab%φ(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) ab≡ab%φ(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) ab≡ab%φ(p)+φ(p)(modp)
细节:每次递归过程中维护的是指数,因此需要在 dfs 出口计算当前的指数,在 qpow 的过程中也通过指数的方式计算
bzoj3884. 上帝与集合的正确用法
链接:https://darkbzoj.tk/problem/3884
题意:给定一个 p ,求 2 2 ⋯ 2 2^{2^{\cdots^2}} 22⋯2 % p ( 1 ≤ p ≤ 1 0 7 ) (1\le p \le 10^7) (1≤p≤107)
#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}} aa…a % 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[r−1]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;
}