欧拉定理
1.引入基本概念
1.1互质
公约数只有1 的两个 整数,称为互质。a与b互质,则写作 (a,b)=1 。
1.2质因数
质因数指能整除给定整数的质数,例如6的质因数为2和3。
1.3余数的基本性质
(a+b)%c = ((a%c)+(b%c)) % c
(a-b)%c = ((a%c) - (b%c)) % c
(a*b)%c = ((a%c) * (b%c)) % c
1.4同余
给定一个正整数m,如果两个整数a和b满足a-b能够被m整除,那么就称整数a与b对模m同余,记作a≡b(mod m)。
2.欧拉函数
2.1定义
对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目.
2.2欧拉函数通式
欧拉函数通式:φ(n)=n*(1-1/p1)*(1-1/p2)*(1-1/p3)*(1-1/p4)*……*(1-1/pn)
p为n的质因数,n是不为0的正整数,φ(1)=1,质数的φ为自己减1 例如φ(2)=1
2.3代码
typedef long long ll;
ll Eular(ll n)
{
ll ans=n;
for(int i=2; i*i <= n; ++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;
}
还可以在素数筛的同时求欧拉函数,效率更高。
3.欧拉定理
3.1定义
对任意两个正整数 a, n,如果两者互质,那么 aφ(n)≡1(mod n)。
3.2证明
先设集合P为小于n且与n互质的正整数集合{q1 , q2 , q3 , … , qφ(n)},这个集合有两个性质:
- qi与n互质
- qi模n后各不相同
再设集合Q为{a*q1%n , a*q2%n , a*q3%n , … , a*qφ(n)%n}
可证:
- 因为a与n互质,所以a*q%n也与n互质,即Q中各元素均与n互质
- 通过反证法,若a*qi%n=a*qj%n,那么
a*qi-a*qj=0 --> a*(qi-qj)=0 --> qi-qj=0 --> qi=qj
因为先前集合P中qi各不相同,所以不成立,可得集合Q中元素各不相同
由上可得P,Q均为包含φ(n)个小于n且n互质且各不相同的元素集合,而这样的集合只有一个,可得P=Q;
所以集合P元素的乘积和集合Q元素的乘积相等:
q1 * q2 * q3 * … * qφ(n)=(a*q1%n) * (a*q2%n) * (a*q3%n) * … * (a*qφ(n)%n)
q1 * q2 * q3 * … * qφ(n)=aφ(n) * (q1 * q2 * q3 * … * qφ(n))%n
同时除q1-qφ(n)即可得
aφ(n)≡1(mod n)
3.3费马小定理
若存在整数a,p,a为整数,p为质数,那么a(p-1)≡ 1(mod p)。
费马小定理是欧拉定理的一种特殊情况(当n为质数时φ(n)为n-1)
4.应用及拓展
4.1求逆元
定义:
对于a*b≡1(mod p),b是a在模m下a的逆元。(只有a与p互质时存在逆元)
意义
余数的基本性质中只包括加减乘,当面对除法时,逆元就相当于是个倒数,可以将除法变为乘法,方便进行模运算。
应用
当p为质数时由费马小定理a(p-1)≡ 1(mod p)得,逆元b为a(p-2);
当p过大时需要使用快速幂进行计算;
当p不是质数时则需使用欧拉定理,提前求出p的欧拉函数,逆元b为a(φ(n)-1)。
时间复杂度为O(nlongn)
4.2欧拉降幂
在求解abmod p时,如果b过大,使用暴力和快速幂是无法求解的,所以这时候就需要用到欧拉降幂来求解。
欧拉降幂公式为 abmod p = a^(b mod φ( p )+φ( p )) mod p
代码:
ll quickpow(ll a,ll b,ll mod)
{
ll res=1%mod;
while (b)
{
if (b & 1) res = (long long)res * a % mod;
a=(long long)a * a % mod;
b >>= 1;
}
return res;
}
ll eular(ll n)
{
ll ans = n;
for(int i=2; i*i <= n; ++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;
}
ll eularpow(ll a,ll b,ll p)
{
ll phi = eular(p);
ll tb = 0;
tb=b%phi+phi;
return quickpow(a,tb,p);
}
int main()
{
ll a,b,p;
cin>>a>>b>>p;
cout<<eularpow(a,b,p);
return 0;
}