背景:
竞赛课,用来补坑吧。
题目传送门:
https://www.luogu.org/problem/P5091
题意:
求
a
b
m
o
d
  
p
a^b\mod p
abmodp。
其中
b
≤
1
0
20000000
b≤10^{20000000}
b≤1020000000。
思路:
扩展欧拉定理:
a
b
=
{
a
b
,
b
<
ϕ
p
a
b
m
o
d
  
ϕ
p
+
ϕ
p
,
b
≥
ϕ
p
a^b=\left\{ \begin{aligned} a^b &,b<\phi_p\\ a^{b\mod \phi_p+\phi_p} &,b≥\phi_p \end{aligned} \right.
ab={ababmodϕp+ϕp,b<ϕp,b≥ϕp
证明不会。
然后套用上面的式子求解即可。
这个操作又称:欧拉降幂。
还是比较简单的。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
int n,p;
int phi[1000010],prime[1000010],f[1000010];
char s[20000010];
void init(int ma)
{
int t=0;
phi[1]=1;
for(int i=1;i<=ma;i++)
{
if(!phi[i]) phi[i]=i-1,prime[++t]=i;
for(int j=1;j<=t&&i*prime[j]<=ma;j++)
{
if(!(i%prime[j]))
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
phi[i*prime[j]]=phi[i]*phi[prime[j]];
}
}
}
int ksm(int x,int k,int mod)
{
int tot=1;
for(;k;k>>=1)
{
if(k&1) tot=(LL)tot*x%mod;
x=(LL)x*x%mod;
}
return tot;
}
int main()
{
scanf("%d %d",&n,&p);
init(p);
scanf("%s",s+1);
int l=strlen(s+1),d=0;
LL tmp=0;
bool bz=true;
for(int i=1;i<=l;i++)
{
d=(d*10+(s[i]-'0'))%phi[p];
tmp=(tmp*10+(s[i]-'0'));
if(tmp>phi[p]) bz=false;
}
printf("%d",ksm(n,bz?tmp:d+phi[p],p));
}