专题 Euler 定理 & EXEuler 定理的概述
概念解释
本文主要介绍关于 Euler,以及 EXEuler 的编码方式还有它们的应用。数学理论会涉及到,但是不会很多。更多的内容会在专门的合集里。
算法分析
在介绍 Euler 定理之前,笔者首先需要介绍 Fermat 小定理。它的基本内容是:
定理1(Fermat-Euler 定理)
设 \((a,m)=1\),则有 \(a^{\varphi(m)} \equiv 1 (\mod m )\)。 \((1)\)
特别地,当 \(p\in Prime\) 时,对任意的 \(a\),有 \(a_{p} \equiv a (\mod p)\)。 \((2)\)
通常,\((2)\) 为 Fermat 小定理,而 \((1)\) 为 Euler 定理。对于这些内容的证明,我们放到初等数论的合集了。
这两个定理的作用一般是求逆。结合快速幂去求,这里就不放模板了,因为也没有,毕竟是一个工具类型的定理。
下面我们再介绍一下 EXEuler。这个本来在初等数论上笔者没有找到参考资料,所以在这里就详细说一下。
定理2(EXEuler,扩展欧拉定理)
对于任意的 \(a,k,n\),有 \(a^{k} \equiv a^{k \mod \varphi(n) + \varphi(n)} (\mod n)\)
事实上,这个定理的证明并不好证。这里也只是介绍它的用途,对于我们编码已然足够了。更多的理论推导,放在了合集里。
这个定理的作用是降幂。给出模板题,感受一下。
参考代码
#include<iostream>
#define int long long
#define rei register int
using namespace std;
int a,m;
string b;
int fpow(int x,int y)
{
int ans=1;
while(y)
{
if(y&1) ans=ans*x%m;
x=x*x%m;
y>>=1;
}
return ans;
}
int get_phi(int n)
{
int ans=n;
for(rei i=2;i<=n/i;i++)
if(n%i==0)
{
ans=ans/i*(i-1);
while(n%i==0) n/=i;
}
if(n>1) ans=ans/n*(n-1);
return ans;
}
int depow(int x)
{
int temp=0,f=0;
for(rei i=0;i<b.size();i++)
{
temp=temp*10+b[i]-'0';
if(temp>=x) f=1,temp%=x;
}
if(f) temp+=x;
return temp;
}
signed main()
{
cin>>a>>m;
cin>>b;
int phi_m=get_phi(m);
int y=depow(phi_m);
cout<<fpow(a,y);
return 0;
}
细节研讨
利用这个手段降幂,然后再用快速幂去求。这样是合理的手段。
总结归纳
配套的理论证明对应在《初等数论》的合集里有。