欧拉定理相关及扩展欧几里得

威尔逊定理、费马定理、欧拉函数、欧拉定理、逆元、exgcd

威尔逊定理: ( p − 1 ) ! ≡ − 1 ( m o d p ) (p-1)! \equiv -1 \pmod p (p1)!1(modp),当且仅当 p p p为质数
其中: ( p − 1 ) ! (p-1)! (p1)!表示 p − 1 p-1 p1的阶乘,即 1 ∗ 2 ∗ 3 ∗ ⋯ ∗ ( p − 1 ) 1*2*3*\dots*(p-1) 123(p1)
证明:
先证充分性: 即“ p p p为质数” → \rightarrow ( p − 1 ) ! ≡ − 1 ( m o d p ) (p-1)! \equiv -1 \pmod p (p1)!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 ij%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 ii%p=1,我们来求 i i i 的值。
i ∗ i % p = 1 i*i\%p=1 ii%p=1
可得: i ∗ i − k ∗ p = 1 i*i-k*p=1 iikp=1
移项可得:
i ∗ i − 1 = k ∗ p i*i-1=k*p ii1=kp

( i + 1 ) ∗ ( i − 1 ) = k ∗ p (i+1)*(i-1)=k*p (i+1)(i1)=kp
因为 p p p为质数,所以:要么 ( i + 1 ) (i+1) (i+1) p p p的倍数,要么 ( i − 1 ) (i-1) (i1) 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=pi1=0
{ i 1 = p − 1 i 2 = 1 \begin{cases} \begin{aligned} i_1&=p-1 \\ i_2&=1 \end{aligned} \end{cases} {i1i2=p1=1
可知:只有当 i i i 1 1 1 p − 1 p-1 p1时, 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 (p1)!%p=123(p1)%p=1(p1)%p=p1.
而p-1和-1是模p等价的。所以充分性得证。
**再证必要性:**即 ( p − 1 ) ! ≡ − 1 ( m o d p ) (p-1)! \equiv -1 \pmod p (p1)!1(modp) → \rightarrow p p p是质数”。
即证“p不是质数” → \rightarrow ( p − 1 ) ! ≢ p − 1 ( m o d p ) (p-1)!\not\equiv p-1\pmod p (p1)!p1(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) 123(p1)一定是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) 123(p1)必为 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) (p1)!%p=(p1)
得证。

费马定理: 如果 p p p为质数,且 a % p ≠ 0 a\%p\neq 0 a%p=0,则有 a p − 1 % p = 1 a^{p-1}\%p=1 ap1%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 (a1)(a2)(a3)(a(p1))%p=ap1(p1)!%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 (a1)%p,(a2)%p,,(a(p1))%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 (a1)(a2)(a3)(a(p1))%p=(p1)!%p(2)
由(1),(2)可知:
a p − 1 ∗ ( p − 1 ) ! % p = ( p − 1 ) ! % p (3) a^{p-1}*(p-1)!\%p=(p-1)!\%p \tag3 ap1(p1)!%p=(p1)!%p(3)
因为 p p p是质数,所以 ( p − 1 ) ! (p-1)! (p1)! p p p互质,所以等式(3)两边同时除以 ( p − 1 ) ! (p-1)! (p1)!,得到:
a p − 1 % p = 1 a^{p-1}\%p=1 ap1%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)=n1.

  • 如果 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)=apap1=ap1(a1)=ap(11/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=a1p1a2p2akpk,根据积性函数的性质,

    ϕ ( 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(11/a1)a2p2(11/a2)akpk(11/ak)=n(11/a1)(11/a2)(11/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\} {ap1%p,ap2%p,,apk%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 (ap1)(ap2)(apk)(p1p2pk)(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 ab%p=1,则称 a , b a,b a,b在模p意义下互为逆元。
只有当a与p互质时,在模p意义下a才有逆元, a a a的逆元记作 a − 1 a^{-1} a1.
逆元的性质:若b与p互质,则 a / b % p = a ∗ b − 1 % p a/b\%p=a*b^{-1}\%p a/b%p=ab1%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 37%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=231%5=27%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[mi]
证明:因为 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](mi)%m=1
所以: f [ m − i ] = − f [ i ] f[m-i]=-f[i] f[mi]=f[i]
2. f [ i ] = k ∗ f [ k ∗ i ] f[i]=k*f[k*i] f[i]=kf[ki]
证明:
因为
f [ i ∗ k ] ∗ ( k ∗ i ) % m = 1 f[i*k]*(k*i)\%m=1 f[ik](ki)%m=1
( f [ k ∗ i ] ∗ k ) ∗ i = 1 (f[k*i]*k)*i=1 (f[ki]k)i=1
f [ i ] = k ∗ f [ k ∗ i ] f[i]=k*f[k*i] f[i]=kf[ki]

扩展欧几里得

扩展欧几里得是用来求不定方程如: 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+(aa/bb)y
将a,b看做变量,移项并合并同类项,可得:
{ x = y ′ y = x ′ − y ′ ∗ ( a / b ) \begin{cases} x=y' \\ y=x'-y'*(a/b) \end{cases} {x=yy=xy(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);
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值