威尔逊定理、费马定理、欧拉函数、欧拉定理、逆元、exgcd
威尔逊定理:
(
p
−
1
)
!
≡
−
1
(
m
o
d
p
)
(p-1)! \equiv -1 \pmod p
(p−1)!≡−1(modp),当且仅当
p
p
p为质数。
其中:
(
p
−
1
)
!
(p-1)!
(p−1)!表示
p
−
1
p-1
p−1的阶乘,即
1
∗
2
∗
3
∗
⋯
∗
(
p
−
1
)
1*2*3*\dots*(p-1)
1∗2∗3∗⋯∗(p−1)。
证明:
先证充分性: 即“
p
p
p为质数”
→
\rightarrow
→
(
p
−
1
)
!
≡
−
1
(
m
o
d
p
)
(p-1)! \equiv -1 \pmod p
(p−1)!≡−1(modp)。
设
0
<
i
<
p
0\lt i \lt p
0<i<p,因为
p
p
p为质数,可知
(
i
,
p
)
=
1
(i,p)=1
(i,p)=1。根据裴蜀定理中的引理二,必存在一个整数
j
(
0
<
j
<
p
)
j(0 \lt j \lt p)
j(0<j<p),使得
i
∗
j
%
p
=
1
i*j\%p=1
i∗j%p=1,称
j
j
j是
i
i
i的逆元,显然
i
i
i的逆元具有唯一性。
而
i
i
i的逆元是有可能等于
i
i
i的。在哪些情况下,
i
i
i的逆元等于
i
i
i呢?
令
i
∗
i
%
p
=
1
i*i\%p=1
i∗i%p=1,我们来求
i
i
i 的值。
由
i
∗
i
%
p
=
1
i*i\%p=1
i∗i%p=1
可得:
i
∗
i
−
k
∗
p
=
1
i*i-k*p=1
i∗i−k∗p=1
移项可得:
i
∗
i
−
1
=
k
∗
p
i*i-1=k*p
i∗i−1=k∗p
即
(
i
+
1
)
∗
(
i
−
1
)
=
k
∗
p
(i+1)*(i-1)=k*p
(i+1)∗(i−1)=k∗p
因为
p
p
p为质数,所以:要么
(
i
+
1
)
(i+1)
(i+1)是
p
p
p的倍数,要么
(
i
−
1
)
(i-1)
(i−1)是
p
p
p的倍数。因为
0
<
i
<
p
0 \lt i \lt p
0<i<p,所以必有:
{
i
+
1
=
p
i
−
1
=
0
\begin{cases} i+1=p \\ i-1=0 \\ \end{cases}
{i+1=pi−1=0
即
{
i
1
=
p
−
1
i
2
=
1
\begin{cases} \begin{aligned} i_1&=p-1 \\ i_2&=1 \end{aligned} \end{cases}
{i1i2=p−1=1
可知:只有当
i
i
i为
1
1
1或
p
−
1
p-1
p−1时,
i
i
i的逆元是它自身。
换句话说,在区间(1,p-1)中,每一个数都有一个不等于自己的唯一的逆元,并且逆元也在这个区间中。即这个区间中的数,可以划分成若干逆元对。
所以,
(
p
−
1
)
!
%
p
=
1
∗
2
∗
3
∗
⋯
∗
(
p
−
1
)
%
p
=
1
∗
(
p
−
1
)
%
p
=
p
−
1
(p-1)!\%p=1*2*3*\dots*(p-1)\%p=1*(p-1)\%p=p-1
(p−1)!%p=1∗2∗3∗⋯∗(p−1)%p=1∗(p−1)%p=p−1.
而p-1和-1是模p等价的。所以充分性得证。
**再证必要性:**即
(
p
−
1
)
!
≡
−
1
(
m
o
d
p
)
(p-1)! \equiv -1 \pmod p
(p−1)!≡−1(modp)
→
\rightarrow
→ “
p
p
p是质数”。
即证“p不是质数”
→
\rightarrow
→
(
p
−
1
)
!
≢
p
−
1
(
m
o
d
p
)
(p-1)!\not\equiv p-1\pmod p
(p−1)!≡p−1(modp).
如果p不是质数,则[2,p-1]中必有p的因子,设其为
i
i
i,则
i
i
i和
p
/
i
p/i
p/i都是
p
p
p的因子。
1.如果
i
≠
p
/
i
i\neq p/i
i=p/i,则
1
∗
2
∗
3
∗
⋯
∗
(
p
−
1
)
1*2*3*\dots*(p-1)
1∗2∗3∗⋯∗(p−1)一定是p的倍数,所以它模
p
p
p一定为0.
2.如果
i
=
p
/
i
i=p/i
i=p/i,则则
1
∗
2
∗
3
∗
⋯
∗
(
p
−
1
)
1*2*3*\dots*(p-1)
1∗2∗3∗⋯∗(p−1)必为
i
i
i的倍数,所以它模
p
p
p必为
i
i
i的倍数。而因为
p
p
p是
i
i
i的倍数,且
i
>
1
i>1
i>1,所以(p-1)不可能是
i
i
i的倍数。所以
(
p
−
1
)
!
%
p
≠
(
p
−
1
)
(p-1)! \%p \neq (p-1)
(p−1)!%p=(p−1)
得证。
费马定理: 如果
p
p
p为质数,且
a
%
p
≠
0
a\%p\neq 0
a%p=0,则有
a
p
−
1
%
p
=
1
a^{p-1}\%p=1
ap−1%p=1
证明:
(
a
∗
1
)
∗
(
a
∗
2
)
∗
(
a
∗
3
)
∗
⋯
∗
(
a
∗
(
p
−
1
)
)
%
p
=
a
p
−
1
∗
(
p
−
1
)
!
%
p
(1)
(a*1)*(a*2)*(a*3)*\dots*(a*(p-1))\%p=a^{p-1}*(p-1)!\%p \tag1
(a∗1)∗(a∗2)∗(a∗3)∗⋯∗(a∗(p−1))%p=ap−1∗(p−1)!%p(1)
又因为:
a与p互质,根据裴蜀定理中的推论,
(
a
∗
1
)
%
p
,
(
a
∗
2
)
%
p
,
…
,
(
a
∗
(
p
−
1
)
)
%
p
(a*1)\%p,(a*2)\%p,\dots,(a*(p-1))\%p
(a∗1)%p,(a∗2)%p,…,(a∗(p−1))%p的结果均互不相等,且在区间[1,p-1]之间,所以:
(
a
∗
1
)
∗
(
a
∗
2
)
∗
(
a
∗
3
)
∗
⋯
∗
(
a
∗
(
p
−
1
)
)
%
p
=
(
p
−
1
)
!
%
p
(2)
(a*1)*(a*2)*(a*3)*\dots*(a*(p-1))\%p=(p-1)!\%p \tag 2
(a∗1)∗(a∗2)∗(a∗3)∗⋯∗(a∗(p−1))%p=(p−1)!%p(2)
由(1),(2)可知:
a
p
−
1
∗
(
p
−
1
)
!
%
p
=
(
p
−
1
)
!
%
p
(3)
a^{p-1}*(p-1)!\%p=(p-1)!\%p \tag3
ap−1∗(p−1)!%p=(p−1)!%p(3)
因为
p
p
p是质数,所以
(
p
−
1
)
!
(p-1)!
(p−1)!与
p
p
p互质,所以等式(3)两边同时除以
(
p
−
1
)
!
(p-1)!
(p−1)!,得到:
a
p
−
1
%
p
=
1
a^{p-1}\%p=1
ap−1%p=1
所以,费马定理得证。
欧拉函数
对一个正整数n,它的欧拉函数记为
ϕ
(
n
)
\phi(n)
ϕ(n),表示不超过n且与n互质的正整数的个数。
ϕ
(
1
)
=
1
\phi(1)=1
ϕ(1)=1
-
如果 n n n为质数,则 ϕ ( n ) = n − 1 \phi(n)=n-1 ϕ(n)=n−1.
-
如果 n = a p n=a^p n=ap,其中 a a a为质数,则 ϕ ( n ) = a p − a p − 1 = a p − 1 ∗ ( a − 1 ) = a p ∗ ( 1 − 1 / a ) \phi(n)=a^p-a^{p-1}=a^{p-1}*(a-1)=a^p*(1-1/a) ϕ(n)=ap−ap−1=ap−1∗(a−1)=ap∗(1−1/a)
-
令 n = a 1 p 1 a 2 p 2 … a k p k n=a_1^{p_1}a_2^{p_2}\dots a_k^{p_k} n=a1p1a2p2…akpk,根据积性函数的性质,
ϕ ( n ) = ϕ ( a 1 p 1 ) ∗ ϕ ( a 2 p 2 ) ∗ ⋯ ∗ ϕ ( a k p k ) = a 1 p 1 ∗ ( 1 − 1 / a 1 ) ∗ a 2 p 2 ∗ ( 1 − 1 / a 2 ) ∗ ⋯ ∗ a k p k ∗ ( 1 − 1 / a k ) = n ∗ ( 1 − 1 / a 1 ) ∗ ( 1 − 1 / a 2 ) ∗ ⋯ ∗ ( 1 − 1 / a k ) \begin{aligned}\phi(n)&= \phi(a_1^{p_1})*\phi(a_2^{p_2})*\dots*\phi(a_k^{p_k}) \\ &=a_1^{p_1}*(1-1/a_1)*a_2^{p_2}*(1-1/a_2)*\dots*a_k^{p_k}*(1-1/a_k)\\ &=n*(1-1/a_1)*(1-1/a_2)*\dots*(1-1/a_k) \end{aligned} ϕ(n)=ϕ(a1p1)∗ϕ(a2p2)∗⋯∗ϕ(akpk)=a1p1∗(1−1/a1)∗a2p2∗(1−1/a2)∗⋯∗akpk∗(1−1/ak)=n∗(1−1/a1)∗(1−1/a2)∗⋯∗(1−1/ak)。
例1:给出一个整数n,求小于n且与n互质的数的个数。
n<=10000000
分析:本题即为求n的欧拉函数。直接通过上述公式来求。
#include<bits/stdc++.h>
using namespace std;
int n;
int getphi(int x)
{
int res=x;
for(int i=2;i*i<=x;i++)
{
if(x%i==0)
{
res=1ll*res*(i-1)/i; //此处要用1ll。否则有可能超出整型范围。
while(x%i==0)
x=x/i;
}
}
if(x>1) //最后要注意判断x是否大于1。因为x中可能包含一个大于其平方根的质因数。
res=1ll*res*(x-1)/x;
return res;
}
int main()
{
scanf("%d",&n);
printf("%d\n",getphi(n));
return 0;
}
例2.给出一个整数n,求区间[1,n]中所有数的欧拉函数值。
n<=10000000
用例1的方法求欧拉函数,时间复杂度为
O
(
n
)
O(\sqrt n)
O(n).如果本题也用这种方法,肯定超时。
我们可以采用类似于质数的筛法来求欧拉函数。
算法时间复杂度为
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
#include<bits/stdc++.h>
using namespace std;
#define MAXN 1000005
int phi[MAXN];
int n,a,b;
void getphi(int x)
{
for(int i=2;i<=x;i++)
{
if(phi[i]==0) //i一定是质数。
{
phi[i]=i-1;
for(int k=2*i;k<=x;k+=i)
{
if(phi[k]==0)phi[k]=k;
phi[k]=phi[k]/i*(i-1); //每个数都被它的质因子筛一下。
}
}
}
}
int main()
{
scanf("%d%d",&a,&b);
if(a>b)swap(a,b);
getphi(b);
for(int i=a;i<=b;i++)
printf("%d\n",phi[i]);
return 0;
}
欧拉定理
如果
a
a
a与
p
p
p互质,则
a
ϕ
(
p
)
%
p
=
1
a^{\phi(p)}\%p=1
aϕ(p)%p=1
其中
ϕ
(
p
)
\phi(p)
ϕ(p)表示
p
p
p的欧拉函数。
证明:
设
p
p
p的简化剩余系为
{
p
1
,
p
2
,
…
,
p
k
}
\{p_1,p_2,\dots,p_k\}
{p1,p2,…,pk},因为
a
a
a与
p
p
p互质,所以
{
a
∗
p
1
%
p
,
a
∗
p
2
%
p
,
…
,
a
∗
p
k
%
p
}
\{a*p_1\%p,a*p_2\%p,\dots,a*p_k\%p\}
{a∗p1%p,a∗p2%p,…,a∗pk%p}也构成了
p
p
p的简化剩余系。
所以:
(
a
∗
p
1
)
∗
(
a
∗
p
2
)
∗
⋯
∗
(
a
∗
p
k
)
≡
(
p
1
∗
p
2
∗
⋯
∗
p
k
)
(
m
o
d
p
)
(a*p_1)*(a*p_2)*\dots*(a*p_k) \equiv (p_1*p_2*\dots*p_k) \pmod p
(a∗p1)∗(a∗p2)∗⋯∗(a∗pk)≡(p1∗p2∗⋯∗pk)(modp)
所以
a
ϕ
(
p
)
≡
1
(
m
o
d
p
)
a^\phi(p) \equiv 1 \pmod p
aϕ(p)≡1(modp)
逆元
如果整数a,b满足
a
∗
b
%
p
=
1
a*b\%p=1
a∗b%p=1,则称
a
,
b
a,b
a,b在模p意义下互为逆元。
只有当a与p互质时,在模p意义下a才有逆元,
a
a
a的逆元记作
a
−
1
a^{-1}
a−1.
逆元的性质:若b与p互质,则
a
/
b
%
p
=
a
∗
b
−
1
%
p
a/b\%p=a*b^{-1}\%p
a/b%p=a∗b−1%p
由此可见,通过逆元,可以将除法取余变为乘法取余。
注意此处的“除法”,不是整除,可以理解为分式。
在模意义下,分式取余是一个整数,比如
2
/
3
%
5
2/3\%5
2/3%5,它是有意义的。因为在模意义下,每一个数表示的是一个同余类。在模5的意义下,2表示的是所有除以5余数为2的整数。所以2表示的是
{
2
,
7
,
12
,
…
,
}
\{2,7,12,\dots,\}
{2,7,12,…,},于是
2
/
3
%
5
2/3\%5
2/3%5和
12
/
3
%
5
12/3\%5
12/3%5是一样的,结果为4.
这种分式取模,我们既可以采用同余等价类来解决,也可以采用逆元来求。采用逆元是更一般的方法。
3在模5意义下的逆元为7,因为
3
∗
7
%
5
=
1
3*7\%5=1
3∗7%5=1。
于是有:
2
/
3
%
5
=
2
∗
3
−
1
%
5
=
2
∗
7
%
5
=
4
2/3\%5=2*3^{-1}\%5=2*7\%5=4
2/3%5=2∗3−1%5=2∗7%5=4.
区间逆元
求区间[1,n]的逆元,如果采用上述求逆元的方法做,时间复杂度为
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
有一种递推的方法可以求区间的逆元,时间复杂度为
O
(
n
)
O(n)
O(n)。
设模数为m,
f
[
n
]
f[n]
f[n]表示
n
n
n的逆元,其中1~(m-1)的逆元已经求出,则
f
[
n
]
=
(
−
f
[
m
%
n
]
∗
(
m
/
n
)
%
m
+
m
)
%
m
f[n]=(-f[m\%n]*(m/n)\%m+m)\%m
f[n]=(−f[m%n]∗(m/n)%m+m)%m.
这个原理是什么呢?
1.设
f
[
i
]
f[i]
f[i]表示
i
i
i在模m下的逆元,则有
f
[
i
]
=
−
f
[
m
−
i
]
f[i]=-f[m-i]
f[i]=−f[m−i]。
证明:因为
f
[
i
]
∗
i
%
m
=
1
f[i]*i\%m=1
f[i]∗i%m=1,
所以:
f
[
i
]
∗
(
−
i
)
%
m
=
−
1
f[i]*(-i)\%m=-1
f[i]∗(−i)%m=−1
即:
−
f
[
i
]
∗
(
m
−
i
)
%
m
=
1
-f[i]*(m-i)\%m=1
−f[i]∗(m−i)%m=1
所以:
f
[
m
−
i
]
=
−
f
[
i
]
f[m-i]=-f[i]
f[m−i]=−f[i]
2.
f
[
i
]
=
k
∗
f
[
k
∗
i
]
f[i]=k*f[k*i]
f[i]=k∗f[k∗i]
证明:
因为
f
[
i
∗
k
]
∗
(
k
∗
i
)
%
m
=
1
f[i*k]*(k*i)\%m=1
f[i∗k]∗(k∗i)%m=1
即
(
f
[
k
∗
i
]
∗
k
)
∗
i
=
1
(f[k*i]*k)*i=1
(f[k∗i]∗k)∗i=1
即
f
[
i
]
=
k
∗
f
[
k
∗
i
]
f[i]=k*f[k*i]
f[i]=k∗f[k∗i]
扩展欧几里得
扩展欧几里得是用来求不定方程如:
a
x
+
b
y
=
c
ax+by=c
ax+by=c。其中,
a
,
b
,
c
a,b,c
a,b,c为已知整数,其中
g
c
d
(
a
,
b
)
∣
c
gcd(a,b) \mid c
gcd(a,b)∣c。这样,不定方程才有解。
扩展欧几里得是用递归的思想来求解的。
我们先求方程
a
x
+
b
y
=
g
c
d
(
a
,
b
)
。
ax+by=gcd(a,b)。
ax+by=gcd(a,b)。求出来该方程的解,则原方程的解乘上系数
(
c
/
g
c
d
(
a
,
b
)
)
(c/gcd(a,b))
(c/gcd(a,b))就可以了。
因为:
a
x
+
b
y
=
g
c
d
(
a
,
b
)
=
g
c
d
(
b
,
a
%
b
)
=
b
x
′
+
(
a
%
b
)
y
′
ax+by=gcd(a,b)=gcd(b,a\%b)=bx'+(a\%b)y'
ax+by=gcd(a,b)=gcd(b,a%b)=bx′+(a%b)y′
a
x
+
b
y
=
b
x
′
+
(
a
%
b
)
y
′
=
b
x
′
+
(
a
−
a
/
b
∗
b
)
y
′
ax+by=bx'+(a\%b)y'=bx'+(a-a/b*b)y'
ax+by=bx′+(a%b)y′=bx′+(a−a/b∗b)y′
将a,b看做变量,移项并合并同类项,可得:
{
x
=
y
′
y
=
x
′
−
y
′
∗
(
a
/
b
)
\begin{cases} x=y' \\ y=x'-y'*(a/b) \end{cases}
{x=y′y=x′−y′∗(a/b)
只需要求出
x
′
,
y
′
x',y'
x′,y′,则可以求出
x
,
y
x,y
x,y。
而求
x
′
,
y
′
x',y'
x′,y′,可以继续递归。这样递归下去,
g
c
d
(
a
,
b
)
gcd(a,b)
gcd(a,b)中的参数b最终会变为0,此时gcd(a,0)=a.
于是有:
a
x
+
b
y
=
g
c
d
(
a
,
0
)
=
a
ax+by=gcd(a,0)=a
ax+by=gcd(a,0)=a,可以求出
x
=
1
,
y
=
0
x=1,y=0
x=1,y=0.这是最底层的
x
,
y
x,y
x,y,然后一层层返回,就可以求出原始的
x
x
x和
y
y
y了。
void exgcd(int a,int b,int &d,int &x,int &y)
{
if(!b)d=a,x=1,y=0;
else
{
exgcd(b,a%b,d,y,x);
y-=x*(a/b);
}
}