1. 程式人生 > >LG5901 【模板】歐拉定理

LG5901 【模板】歐拉定理

lin flag sam 說明 輸出 its cpp 分析 math

題意

題目描述

給你三個正整數,$a,m,b$,你需要求:
$a^b \mod m$

輸入輸出格式

輸入格式:

一行三個整數,$a,m,b$

輸出格式:

一個整數表示答案

輸入輸出樣例

輸入樣例#1: 復制
2 7 4
輸出樣例#1: 復制
2
輸入樣例#2: 復制
998244353 12345 98765472103312450233333333333
輸出樣例#2: 復制
5333

說明

註意輸入格式,$a,m,b$ 依次代表的是底數、模數和次數

樣例1解釋:
$2^4 \mod 7 = 2$
輸出2

數據範圍:
對於全部數據:
$1≤a≤10^9$
$1≤b≤10^{20000000}$
$1≤m≤10^6$

分析

費馬小定理

\(a,p\in \mathbb{Z}\)\(p\) 為質數,且 \(a\not\equiv 0\pmod{p}\) 時有:
\(a^{p-1}\equiv 1\pmod{p}\)

所以 \(a^b\equiv a^{b\bmod (p-1)}\pmod p\)

歐拉定理

\(a,m\in \mathbb{Z}\) ,且 \(\gcd(a,m)=1\) 時有:
\(a^{\varphi(m)}\equiv 1\pmod{m}\)

這裏 \(\varphi(x)\) 是數論中的歐拉函數。

所以 \(a^b\equiv a^{b\bmod \varphi(m)}\pmod m\)

擴展歐拉定理

\(a,m\in \mathbb{Z}\) 時有:
\(a^b\equiv\left\{\begin{matrix}a^b&,b<\varphi(m)\\a^{b\bmod\varphi(m)+\varphi(m)}&,b\ge\varphi(m)\end{matrix}\right.\pmod m\)

對於那個高精度整數,一邊乘10相加,一遍取模即可。時間復雜度\(O(\sqrt m+\lg b+\log_2 m)\)

代碼

#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
    rg T data=0,w=1;rg char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') w=-1;ch=getchar();}
    while(isdigit(ch)) data=data*10+ch-'0',ch=getchar();
    return data*w;
}
template<class T>il T read(rg T&x) {return x=read<T>();}
typedef long long ll;

int main(){
    int a=read<int>(),m=read<int>();
    
    int phi=m,mm=m;
    for(int i=2;i*i<=mm;++i)if(mm%i==0){
        phi=phi/i*(i-1);
        while(mm%i==0) mm/=i;
    }
    if(mm>1) phi=phi/mm*(mm-1);
    
    int b=0,flag=0;
    char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)){
        b=b*10+ch-'0',ch=getchar();
        if(b>=phi) b%=phi,flag=1;
    }
    if(b>=phi) b%=phi,flag=1;
    if(flag) b+=phi;
    
    int ans=1;
    for(;b;b>>=1,a=(ll)a*a%m)
        if(b&1) ans=(ll)ans*a%m;
    printf("%d\n",ans);
    return 0;
}

LG5901 【模板】歐拉定理