拓展欧拉定理学习笔记
拓展欧拉定理
内容
对于 \(a,m\in \mathbb{Z}\),有 \(a^b \equiv \begin{cases}a^b&b< \varphi(m) \\a^{\left( b \bmod \varphi(m) \right)+\varphi(m)}&b>\varphi(m)\end{cases} \pmod{p}\)
证明
略
模板
给定三个数 \(a,m,b\in\mathbb{Z}\),求 \(a^b \bmod m\)。
\(1 \le m \le 10^8,1 \le b \le 10^{20000000}, 1 \le a \le 10^9\)
首先根据拓展欧拉定理的内容,先求出 \(\varphi(m)\):
int ph(int x){
int s=x;
for(int i=2;i*i<=x;i++)if(x%i==0){s-=s/i;while(x%i==0)x/=i;}
if(x>1)s-=s/x;return s;
}
至于 \(b\) 的读入,考虑按位读入,读入的同时取模并判断是否大于 \(\varphi(m)\)。
int rd(){
int x=0;char c=getchar();while(c<'0'||c>'9')c=getchar();
while(c>='0'&&c<='9'){x*=10,x+=(c^'0');if(x>=mod)f=1;x%=mod;c=getchar();}return x;
}
剩下的就是一个快速幂了,因为全定义了全局变量所以没有传参。
int ksm(){int s=1,g=a;while(b){if(b&1)s=s*g%m;b>>=1;g=g*g%m;}return s;}
最后放一下完整代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;int mod,a,m,b,f;int ph(int x){
int s=x;for(int i=2;i*i<=x;i++)if(x%i==0){s-=s/i;while(x%i==0)x/=i;}
if(x>1)s-=s/x;return s;
}int ksm(){int s=1,g=a;while(b){if(b&1)s=s*g%m;b>>=1;g=g*g%m;}return s%m;}int rd(){
int x=0;char c=getchar();while(c<'0'||c>'9')c=getchar();
while(c>='0'&&c<='9'){x*=10,x+=(c^'0');if(x>=mod)f=1;x%=mod;c=getchar();}return x;
}signed main(){cin>>a>>m;mod=ph(m);b=rd();if(f)b+=mod;cout<<ksm();}