欧拉定理:若 a , m a,m a,m互质则有: a φ ( m ) ≡ 1 ( m o d m ) a^{\varphi(m)}\equiv 1\pmod{m} aφ(m)≡1(modm)
当 m m m为素数 p p p时,欧拉定理退化为费马小定理: a p − 1 ≡ 1 ( m o d p ) a^{p-1}\equiv 1\pmod{p} ap−1≡1(modp)
欧拉定理的推论: a b ≡ a b ( m o d φ ( m ) ) ( m o d m ) , ( a , m a^b\equiv a^{b\pmod{\varphi(m)}} \pmod{m},(a,m ab≡ab(modφ(m))(modm),(a,m互质 ) ) )
证明:
记 b = k φ ( m ) + t , t = b ( m o d φ ( m ) ) b=k\varphi(m)+t,t=b\pmod{\varphi(m)} b=kφ(m)+t,t=b(modφ(m))
有 a b = a k φ ( m ) + t = ( a φ ( m ) ) k × a t = 1 k × a b ( m o d φ ( m ) ) = a b ( m o d φ ( m ) ) ( m o d m ) a^b\\=a^{k\varphi(m)+t}\\=(a^{\varphi(m)})^k\times a^t\\=1^k\times a^{b\pmod{\varphi(m)}}\\=a^{b\pmod{\varphi(m)}} \pmod{m} ab=akφ(m)+t=(aφ(m))k×at=1k×ab(modφ(m))=ab(modφ(m))(modm)
证毕。
扩展欧拉定理: a b ≡ a b m o d φ ( m ) + φ ( m ) ( m o d m ) , b ≥ φ ( m ) a^b\equiv a^{b\bmod \varphi(m)+\varphi(m)}\pmod{m}, b\ge\varphi(m) ab≡abmodφ(m)+φ(m)(modm),b≥φ(m)
简要证明:
1.当 a , m a,m a,m互质显然成立。
2.当 a , m a,m a,m不互质时。
对 m m m进行素数分解: m = ∏ i = 1 k p i q i m=\prod\limits_{i=1}^k p_i^{q_i} m=i=1∏kpiqi
只需证明对任意 p i q i p_i^{q_i} piqi满足: a b ≡ a b m o d φ ( m ) + φ ( m ) ( m o d p i q i ) a^b\equiv a^{b\bmod \varphi(m)+\varphi(m)}\pmod{p_i^{q_i}} ab≡abmodφ(m)+φ(m)(modpiqi)
p o s 1 : pos_1: pos1:当 g c d ( a , p i q i ) = 1 gcd(a,p_i^{q_i})=1 gcd(a,piqi)=1时,显然成立。
p o s 2 : pos_2: pos2:当 g c d ( a , p i q i ) ≠ 1 gcd(a,p_i^{q_i})\ne1 gcd(a,piqi)=1时, a a a肯定为 p i p_i pi的倍数,即 a = n p i a=np_i a=npi,又因为 φ ( p i q i ) = p i q i − 1 ( p i − 1 ) \varphi(p_i^{q_i})=p_i^{q_i-1}(p_i-1) φ(piqi)=piqi−1(pi−1),可以证得: φ ( p i q i ) ≥ q i \varphi(p_i^{q_i})\ge q_i φ(piqi)≥qi
所以: b ≥ φ ( m ) ≥ φ ( p i q i ) ≥ q i b\ge \varphi(m)\ge \varphi(p_i^{q_i})\ge q_i b≥φ(m)≥φ(piqi)≥qi
所以 p i q i p_i^{q_i} piqi是 a b m o d φ ( m ) + φ ( m ) a^{b\bmod \varphi(m)+\varphi(m)} abmodφ(m)+φ(m)的因数,同时也是 a b a^b ab的因数。
即: a b ≡ a b m o d φ ( m ) + φ ( m ) ≡ 0 ( m o d p i q i ) a^b\equiv a^{b\bmod \varphi(m)+\varphi(m)}\equiv 0\pmod{p_i^{q_i}} ab≡abmodφ(m)+φ(m)≡0(modpiqi)
综上: a b ≡ a b m o d φ ( m ) + φ ( m ) ( m o d m ) , ( b ≥ φ ( m ) ) a^b\equiv a^{b\bmod \varphi(m)+\varphi(m)}\pmod{m},(b\ge\varphi(m)) ab≡abmodφ(m)+φ(m)(modm),(b≥φ(m))
参考:传送门
例题:
1.板子题:P5091 【模板】扩展欧拉定理
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
bool f;
inline void read(int &s){ //快读
int w=1;char c;
while(c=getchar(),!isdigit(c)){
if(c=='-') w=-1;
}
while(isdigit(c)) s=(s<<3)+(s<<1)+(c&15),c=getchar();
s*=w;
}
inline int readm(int m){ //取模快读
int s=0;char c;while(c=getchar(),!isdigit(c)) ;
while(isdigit(c)){
s=(s<<3)+(s<<1)+(c&15);
if(s>=m){
s%=m;
f=true;
}
c=getchar();
}
return s;
}
int phi(int n){ //求phi(n)
int s=n;
for(int i=2;i*i<=n;i++){
if(n%i==0){
s-=s/i;
while(n%i==0) n/=i;
}
}
if(n>1) s-=s/n;return s;
}
int a,m,b;
ll ksm(ll a,ll n,ll m){ //快速幂
ll ans=1;
while(n){
if(n&1) ans=ans*a%m;
a=a*a%m;
n>>=1;
}
return ans;
}
int main(){
read(a),read(m);int phim=phi(m);b=readm(phim);
printf("%lld\n",ksm(a,b+(f?phim:0),m));
return 0;
}
2.U55950 【模板】扩展欧拉定理 (数据加强版)
因为 a , m ≤ 1 0 12 a,m\le 10^{12} a,m≤1012,所以直接 k s m ksm ksm时会爆 l o n g l o n g long\ long long long,这时候需要用到龟速乘,来处理取模意义下的 a × a ( m o d m ) , a n s × a ( m o d m ) a\times a \pmod{m},ans\times a\pmod{m} a×a(modm),ans×a(modm)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
bool f;
inline void read(ll &s){
int w=1;char c;
while(c=getchar(),!isdigit(c)){
if(c=='-') w=-1;
}
while(isdigit(c)) s=(s<<3)+(s<<1)+(c&15),c=getchar();
s*=w;
}
inline ll readm(ll m){
ll s=0;char c;while(c=getchar(),!isdigit(c)) ;
while(isdigit(c)){
s=(s<<3)+(s<<1)+(c&15);
if(s>=m){
s%=m;
f=true;
}
c=getchar();
}
return s;
}
ll phi(ll n){
ll s=n;
for(ll i=2;i*i<=n;i++){
if(n%i==0){
s-=s/i;
while(n%i==0) n/=i;
}
}
if(n>1) s-=s/n;return s;
}
ll qmul(ll x,ll y,ll m){ //龟速乘 比x*y慢,但是能在取模意义下获得正确值
ll s=0;
while(y){
if(y&1) s=(s+x)%m;
x=(x+x)%m;
y>>=1;
}
return s;
}
ll a,m,b;
ll ksm(ll a,ll n,ll m){
ll ans=1;
while(n){
if(n&1) ans=qmul(ans,a,m);
a=qmul(a,a,m);
n>>=1;
}
return ans;
}
int main(){
read(a),read(m);ll phim=phi(m);b=readm(phim);
printf("%lld\n",ksm(a,b+(f?phim:0),m));
return 0;
}