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 oula(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)
费马小定理结论:结论是若存在整数 a , p 且gcd(a,p)=1,即二者互为质数,则有a(p-1)≡ 1(mod p)。(这里的 ≡ 指的是恒等于,a(p-1)≡ 1(mod p)是指a的p-1次幂取模与1取模恒等),再进一步就是ap≡a(mod p)。
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
4.3 扩展欧拉定理
对于模意义下的指数运算,欧拉定理为我们提供了一个很好的等式利用此等式我们可以很好的解决对于特别大情况如。
若前提的互素条件不一定成立时,则这个等式不能达到需求,而扩展欧拉定理通过对时两者素因子的分析,也可以让运算下降到的级别
证明
1.若结论即为普通的欧拉定理
2.若,考察a,m的一个相同素因子p,其中且m1无素因子p
对于每个a的素因子都进行这种操作,若直接利用欧拉定理
若将所有的素因子作用一次后取乘积即可得到
ps:可以看出上述的证明2部分中界不是最优的,但考虑实际计算时可以让指数化解到级别通过快速幂即可快速计算
以luoguP5091 【模板】扩展欧拉定理
题目描述
给你三个正整数,a,m,ba,m,b,你需要求:a^b \bmod mabmodm
输入格式
一行三个整数,a,m,ba,m,b
输出格式
一个整数表示答案
输入输出样例
输入 #1
2 7 4输出 #1
2
输入 #2
998244353 12345 98765472103312450233333333333输出 #2
5333
#include<bits/stdc++.h>
using namespace std;
int a,m,fai=1,b;
int temp,flag=0;
int main()
{
scanf("%d%d",&a,&m);
a%=m;
temp=m;
for(int i=2;i*i<=temp;++i)//扩展欧拉,求出fai
{
if(temp%i) continue;
fai*=i-1;
temp/=i;
while(temp%i==0)
{
fai*=i;
temp/=i;
}
}
if(temp>1)
{
fai*=temp-1;
}
char ch=getchar();
while(!isdigit(ch))
ch=getchar();//快读入b,并随时取模
while(isdigit(ch))
{
b=b*10ll+ch-'0';
if(b>=fai)
{
flag=true;
b%=fai;
}
ch=getchar();
}
if(flag)
{
b+=fai;
}
int ans=1;
int e=b;
for(;e;e>>=1,a=(long long)a*a%m)
{
if(e&1)
ans=(long long)ans*a%m;
}
cout<<ans<<endl;
return 0;
}