专栏文章
题解:P5091 【模板】扩展欧拉定理
P5091题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @mior6aa7
- 此快照首次捕获于
- 2025/12/02 23:48 3 个月前
- 此快照最后确认于
- 2025/12/02 23:48 3 个月前
题解:P5091 【模板】扩展欧拉定理
欧拉函数
欧拉函数定义
欧拉函数(Euler's totient function),即 ,表示的是小于等于 并且 互质的正整数的个数。
形式化的讲,若集合 ,则 ,其中, 表示有限集 中的元素个数(见人教 版数学必修一第 页)。
举个例子,,。
欧拉函数实现
方法一:暴力
循环 从 到 ,对于每一个 ,求 是否为 , 为 是 的次数。
函数的时间复杂度为 ,由于重复 次,所以整体时间复杂度为 。
方法二:质因数分解
若
由唯一分解定理,有
证明如下:

代码如下:
CPPll phi(ll n){
ll ans=n;
for(register int i=2;i*i<=n;i++){
if(!(n%i)){
while(!(n%i))n/=i;
ans/=i;
ans*=(i-1);
}
}
if(n>1){
ans/=n,ans*=(n-1);
}
return ans;
}
时间复杂度 。
欢迎大家在练习题目中提交。
费马小定理
费马小定理是欧拉定理的一个推论。
若 为质数,,且 ,则
证明见 OI-Wiki。
欧拉定理
当 ,且 时有:
所以
(\operatorname{mod} n) $$
证明见 [OI-Wiki](https://oi-wiki.org/math/number-theory/fermat/#证明_1)。
当 $n \in \text{prime}$ 时,$\varphi(n)=n-1$,有
a^b \equiv a^{b \operatorname{mod} (n-1)}(\operatorname{mod} n)
即费马小定理,所以费马小定理是欧拉定理的一个推论。
## [拓展欧拉定理](https://oi-wiki.org/math/number-theory/fermat/#扩展欧拉定理)
本题重点。
a^b \equiv \left{ \begin{array}{rcl}
a^{b \operatorname{mod} \varphi(n)}, & \gcd(a,n)=1,\
a^b & \gcd(a,n) \neq 1, &b<\varphi(n), \
a^{(b \operatorname{mod} \varphi(n))+\varphi(n)}& \gcd(a,n) \neq 1,&b \geq \varphi(n),
\end{array}\right. \lparen \operatorname{mod} n \rparen.
证明见 [OI-Wiki](https://oi-wiki.org/math/number-theory/fermat/#证明_2)
现在,前置知识讲完了,我们来梳理一下思路:

## 代码(共建美好洛谷,请勿抄袭)
注释代码是我的部分数论模版,供选用。
```cpp
#include<bits/stdc++.h>
using namespace std;
const unsigned long long N=6e5+5,M=6e5+5,prime=233317,Mod=212370440129904639,base=131;
typedef unsigned long long ll;
//#define int ll
ll n,p,a,b,m,mod;
#define inf 0x3f3f3f3f
#define mark 20250723222447
ll gcd(int x,int y){
int i,j;
if(x==0)return y;
if(y==0)return x;
for(i=0;(x&1)==0;i++)x>>=1;
for(j=0;(y&1)==0;j++)y>>=1;
if(j<i)i=j;
while(1){
if(x<y)x^=y,y^=x,x^=y;
if(0==(x-=y))return y<<i;
while(0==(x&1))x>>=1;
}
}
//ll x,y;
//inline void exgcd(ll a,ll b){
// if(!b){
// x=1,y=0;
// return;
// }
// exgcd(b,a%b);
// ll k;
// k=x;x=y;
// y=k-a/b*y;
//}
ll fpm(ll x,ll power,ll mod){//快速幂
x%=mod;
ll ans=1;
for(;power;power>>=1,(x*=x)%=mod)
if(power&1)(ans*=x)%=mod;
return ans;
}
//ll inv[3000005];
//ll niyuan(ll n,ll p,ll mod){
// inv[1]=1;
// for(register int i=2;i<=n;i++){
// inv[i]=(p-p/i)*inv[p%i]%mod;
// }
// return inv[n];
//}
//ll niyuan2(ll a,ll b){
// exgcd(a,b);
// x=(x+b)%b;
// return x;
//}
bool flag;
ll getll(ll mod){//读入部分
ll res=0;char ch;
while(!(ch>='0' && ch<='9') && ch!=EOF){
ch=getchar();
}
while((ch>='0' && ch<='9')){
res=(res<<3)+(res<<1)+(ch-'0');//等价于 res=res*10+(ch-'0')
if(res>=mod)flag=true;
res%=mod;
ch=getchar();
}
return res;
}
ll phi(ll n){//欧拉函数
ll ans=n;
for(register int i=2;i*i<=n;i++){
if(!(n%i)){
while(!(n%i))n/=i;
ans/=i;
ans*=(i-1);
}
}
if(n>1){
ans/=n,ans*=(n-1);
}
return ans;
}
ll phm=0;
ll exeut(ll a,ll b,ll m){//Extended Euler's theorem的自创缩写qwq
ll phm=phi(m);
if(gcd(a,m)==1)return fpm(a,b%phm,m);
if(!flag)return fpm(a,b,m);
else return fpm(a,(b%phm)+phm,m);
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
a=getll(1e10);m=getll(1e10);
phm=phi(m);
b=getll(phm);
cout<<exeut(a,b,m);
return 0;
}
``````相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...