数论之阶与原根讲解

前言:

本来想写BSGS算法,但是笔者今天想打游戏 感觉先写原根会更好一点,所以我们今天重点讨论一下什么是原根、哪些整数有原根、原根的性质和求解。
 

提要:

为了减少后面的阅读障碍,先简单介绍一下欧拉函数

φ

(

x

)

\varphi(x)

φ(x),主要部分后面放积性函数那介绍。(ps:书上符号写的是

ϕ

(

x

)

\phi(x)

ϕ(x),但网上写的是

φ

(

x

)

\varphi(x)

φ(x),不过这不重要)
欧拉函数

φ

(

x

)

\varphi(x)

φ(x)的函数值是,小于

x

x

x且与

x

x

x互质的正整数的个数。
比如

φ

(

6

)

=

2

\varphi(6)=2

φ(6)=2,因为小于

6

6

6的正整数中,仅有

1

1

1

5

5

5与其互质。
容易发现,

p

p

p为素数时,有

φ

(

x

)

=

p

1

\varphi(x)=p-1

φ(x)=p1
还有欧拉定理:若

g

c

d

(

a

,

n

)

=

1

gcd(a,n)=1

gcd(a,n)=1,则

a

φ

(

n

)

1

(

m

o

d
  

p

)

a^{\varphi(n)}\equiv1(mod\;p)

aφ(n)1(modp)
 
差不多先这些,开始正文。
 

整数的阶:

什么是阶?

a

a

a

n

n

n是互素的整数,

a

0

,

n

>

0

a\neq 0,n>0

a=0,n>0,使得

a

x

1

(

m

o

d
  

n

)

a^{x}\equiv1(mod\;n)

ax1(modn)成立的最小正整数

x

x

x称为

a

a

a

n

n

n的阶,符号表示为

o

r

d

n

a

ord_{n}a

ordna
 
比如要求

2

2

2

7

7

7的阶,我们一一列举,

2

1

2

(

m

o

d
  

7

)

2

2

4

(

m

o

d
  

7

)

2

3

1

(

m

o

d
  

7

)

2^{1}\equiv2(mod\;7),2^{2}\equiv4(mod\;7),2^{3}\equiv1(mod\;7)

212(mod7)224(mod7)231(mod7)
那么我们称

2

2

2

7

7

7的阶就是

3

3

3,记为

o

r

d

7

2

=

3

ord_{7}2=3

ord72=3
 
现在我们观察方程

a

x

1

(

m

o

d
  

n

)

a^{x}\equiv1(mod\;n)

ax1(modn)
那么显然根据欧拉定理,我们可以知道

φ

(

n

)

\varphi(n)

φ(n)是方程的一个解,但它未必是最小的,所以不一定是阶,而当

φ

(

n

)

\varphi(n)

φ(n)

a

a

a

n

n

n的阶时,我们称

a

a

a

n

n

n的一个原根,这个放后面介绍。

现在继续来讲阶。
 
定理一:若

g

c

d

(

a

,

n

)

=

1

gcd(a,n)=1

gcd(a,n)=1,则

x

0

x_{0}

x0是方程

a

x

1

(

m

o

d
  

n

)

a^{x}\equiv1(mod\;n)

ax1(modn)的一个解的充要条件是

o

r

d

n

a

x

ord_{n}a|x

ordnax。(其中

|

是整除符号,表示

o

r

d

n

a

ord_{n}a

ordna整除

x

x

x)
这个必要性很好证明,既然

a

o

r

d

n

a

1

(

m

o

d
  

n

)

a^{ord_{n}a}\equiv1(mod\;n)

aordna1(modn),那

a

k

×

o

r

d

n

a

1

(

m

o

d
  

n

)

a^{k\times ord_{n}a}\equiv1(mod\;n)

ak×ordna1(modn)当然也成立。
然后充分性,假设存在

x

1

x1

x1不整除

x

0

x_{0}

x0且满足方程,令

x

1

=

k

×

o

r

d

n

a

+

d

x_{1}=k\times ord_{n}a+d

x1=k×ordna+d(其中

d

d

d不整除

o

r

d

n

a

ord_{n}a

ordna)满足方程,那么

d

d

d一定比

o

r

d

n

a

ord_{n}a

ordna小,且满足

a

d

1

(

m

o

d
  

n

)

a^{d}\equiv1(mod\;n)

ad1(modn),那它才是原根嘛。
这样就证好了。

定理二:若

g

c

d

(

a

,

n

)

=

1

gcd(a,n)=1

gcd(a,n)=1,则

o

r

d

n

a

ord_{n}a

ordna能整除

φ

(

n

)

\varphi(n)

φ(n)
前面看下来应该也能想到,且由定理一发现显然嘛。
这时候我们容易想到一个

o

(

n

l

o

g

)

o(\sqrt{n} log)

o(n
log)
求阶的办法,因为

n

n

n的阶一定是

φ

(

n

)

\varphi(n)

φ(n)的因子,所以可以暴力枚举其因子,再看看是不是满足条件。

定理三:若

g

c

d

(

a

,

n

)

=

1

gcd(a,n)=1

gcd(a,n)=1,则

a

i

a

j

(

m

o

d
  

n

)

a^i\equiv a^j(mod\;n)

aiaj(modn)的充要条件是

i

j

(

m

o

d
  

o

r

d

n

a

)

i\equiv j(mod\;ord_{n}a)

ij(modordna)
定理比较重要,自己意会一下。

定理四:若

o

r

d

n

a

=

t

ord_{n}a=t

ordna=t,且

u

u

u为正整数,则有

o

r

d

n

(

a

u

)

=

t

g

c

d

(

t

,

u

)

ord_{n}(a^{u})=\frac{t}{gcd(t,u)}

ordn(au)=gcd(t,u)t
打个比方体会一下,

2

3

1

(

m

o

d
  

7

)

2^3\equiv1(mod\;7)

231(mod7),那么就有

8

1

1

(

m

o

d
  

7

)

8^1\equiv1(mod\;7)

811(mod7)。其实就是这个

3

3

3的因子,这样想就容易理解多了吧。
 
 

原根:

a

a

a

n

n

n的阶为

φ

(

n

)

\varphi(n)

φ(n),也就是说当且仅当

x

x

x

φ

(

n

)

\varphi(n)

φ(n)的倍数,使得

a

x

1

(

m

o

d
  

n

)

a^{x}\equiv1(mod\;n)

ax1(modn)成立,此时称

a

a

a

n

n

n的原根。
 
那么知道了

n

n

n的原根

a

a

a后,有什么好处呢,可以举一个例子。
我们举998244353的原根3, 我们举一个素数

7

7

7的一个原根

3

3

3,然后列举

3

3

3的幂次模

7

7

7

3

1

3

(

m

o

d
  

7

)

3

2

2

(

m

o

d
  

7

)

3

3

6

(

m

o

d
  

7

)

3

4

4

(

m

o

d
  

7

)

3

5

5

(

m

o

d
  

7

)

3

6

1

(

m

o

d
  

7

)

3^{1}\equiv3(mod\;7),3^{2}\equiv2(mod\;7),3^{3}\equiv6(mod\;7),3^{4}\equiv4(mod\;7),3^{5}\equiv5(mod\;7),3^{6}\equiv1(mod\;7)

313(mod7)322(mod7)336(mod7)344(mod7)355(mod7)361(mod7)
然后发现这些余数构成了一个模

7

7

7的完全剩余系

1

,

2

,

3

,

4

,

5

,

6

1,2,3,4,5,6

1,2,3,4,5,6,也就是对于任意

a

a

a,都可以找到

x

0

x_{0}

x0使得

3

x

0

a

(

m

o

d
  

7

)

3^{x_{0}}\equiv a(mod\;7)

3x0a(mod7)
这是素数的情况,现在我们来康康非素数的情况,举

18

18

18的一个原根

5

5

5。然后列举

5

5

5的幂次模

18

18

18

5

1

5

(

m

o

d
  

18

)

5^{1}\equiv5(mod\;18),

515(mod18)

5

2

7

(

m

o

d
  

18

)

5^{2}\equiv7(mod\;18),

527(mod18)

5

3

17

(

m

o

d
  

18

)

5^{3}\equiv17(mod\;18),

5317(mod18)

5

4

13

(

m

o

d
  

18

)

5^{4}\equiv13(mod\;18),

5413(mod18)

5

5

11

(

m

o

d
  

18

)

5^{5}\equiv11(mod\;18),

5511(mod18)

5

6

1

(

m

o

d
  

18

)

5^{6}\equiv1(mod\;18)。

561(mod18)

5

7

5

(

m

o

d
  

18

)

5^{7}\equiv5(mod\;18),

575(mod18)

5

8

7

(

m

o

d
  

18

)

5^{8}\equiv7(mod\;18),

587(mod18)

5

9

17

(

m

o

d
  

18

)

5^{9}\equiv17(mod\;18),

5917(mod18)

5

10

13

(

m

o

d
  

18

)

5^{10}\equiv13(mod\;18),

51013(mod18)

5

11

11

(

m

o

d
  

18

)

5^{11}\equiv11(mod\;18),

51111(mod18)

5

12

1

(

m

o

d
  

18

)

5^{12}\equiv1(mod\;18)。

5121(mod18)

5

13

5

(

m

o

d
  

18

)

5^{13}\equiv5(mod\;18),

5135(mod18)

5

14

7

(

m

o

d
  

18

)

5^{14}\equiv7(mod\;18),

5147(mod18)

5

15

17

(

m

o

d
  

18

)

5^{15}\equiv17(mod\;18),

51517(mod18)

5

16

13

(

m

o

d
  

18

)

5^{16}\equiv13(mod\;18),

51613(mod18)

5

17

11

(

m

o

d
  

18

)

5^{17}\equiv11(mod\;18),

51711(mod18)

5

18

1

(

m

o

d
  

18

)

5^{18}\equiv1(mod\;18)。

5181(mod18)
很容易发现以

6

6

6个为一组,那这个

6

6

6是什么呢?
其实是

φ

(

18

)

=

6

\varphi(18)=6

φ(18)=6。然后出现的数字

1

,

5

,

7

,

11

,

13

,

17

1,5,7,11,13,17

1,5,7,11,13,17,正是与

18

18

18互质的那

6

6

6个数啊。
那么前面素数的情况也说得通了。
所以我们就可以得到,
定理一:若

g

c

d

(

a

,

n

)

=

1

gcd(a,n)=1

gcd(a,n)=1,则

a

1

,

a

2

,

,

a

φ

(

n

)

a^{1},a^{2},……,a^{\varphi(n)}

a1,a2,,aφ(n)构成模

n

n

n的既约剩余系。
大概懂了就不证明了。
而当

p

p

p为素数时,我们就可以将求解方程

x

5

a

(

m

o

d
  

p

)

x^{5}\equiv a(mod\;p)

x5a(modp)的问题代换为求解

g

5

x

a

(

m

o

d
  

p

)

g^{5x}\equiv a(mod\;p)

g5xa(modp),其中

g

g

g

p

p

p的原根,因为

g

g

g的幂次是模

n

n

n的完全剩余系,所以可以用

g

x

g^{x}

gx来代换

x

x

x,这样我们只要求出新方程的

x

0

x_{0}

x0,那么原方程的解就可以求出来了。
 
下一个,
定理二:如果一个数

n

n

n有原根,那么他有多少个不同余的原根,
答案是

φ

(

φ

(

n

)

)

\varphi(\varphi(n))

φ(φ(n))个。
伪证明:由前面阶那里的定理四,我们可以知道

o

r

d

n

(

a

u

)

=

t

g

c

d

(

t

,

u

)

ord_{n}(a^{u})=\frac{t}{gcd(t,u)}

ordn(au)=gcd(t,u)t,那么当

a

a

a

n

n

n的原根时,就有

o

r

d

n

a

=

φ

(

n

)

ord_{n}a=\varphi(n)

ordna=φ(n)
于是我们得到,

o

r

d

n

(

a

u

)

=

φ

(

n

)

g

c

d

(

φ

(

n

)

,

u

)

ord_{n}(a^{u})=\frac{\varphi(n)}{gcd(\varphi(n),u)}

ordn(au)=gcd(φ(n),u)φ(n)
所以要使

o

r

d

n

(

a

u

)

ord_{n}(a^{u})

ordn(au)等于

φ

(

n

)

\varphi(n)

φ(n),就要满足

g

c

d

(

φ

(

n

)

,

u

)

gcd(\varphi(n),u)

gcd(φ(n),u),在

1

1

1

φ

(

n

)

1

\varphi(n)-1

φ(n)1范围里自然就有

φ

(

φ

(

n

)

)

\varphi(\varphi(n))

φ(φ(n))个满足条件的。

吃饭去了,回来再写。

现在研究哪些数是有原根的,也就是原根的存在性
因为刚吃了饭,我懒了。
先证明素数都是有原根的。
再证明奇素数的幂都是有原根的。
然后讨论关于

2

2

2的幂次,发现

2

2

2

4

4

4是有原根的,其他

2

2

2的幂次都没有原根。
然后再发现

2

2

2乘上奇素数的幂也是有原根的。
最后再证明剩下的都没有原根。
于是,得出结论:
定理三:

2

2

2

4

4

4,和奇素数的正整数幂次

p

k

p^{k}

pk,以及

2

2

2乘上奇素数的正整数幂次

2

p

k

2p^{k}

2pk都是有原根的。
 
 
最后,再研究一下怎么求

p

p

p的原根。传送门
先给出一种暴力的解法。(没有第二种了)
先判断有无原根。

2

2

2的原根是

1

1

1

3

3

3的原根是2,

4

4

4的原根是

3

3

3直接特判掉。
然后我们暴力枚举

[

2

,

p

1

]

[2,p-1]

[2,p1],再判断它是不是

p

p

p的原根,枚举的时候当然还要保证与模数互质。
至于要判断

i

i

i是不是

p

p

p的原根,只要看是否存在

x

0

x_{0}

x0

φ

(

p

)

\varphi(p)

φ(p)小,且满足

i

x

0

1

(

m

o

d
  

p

)

i^{x_{0}}\equiv 1(mod\;p)

ix01(modp)
但是我们不至于再去一个一个枚举

x

0

x_{0}

x0,因为我们知道它的阶是满足方程的,而阶的倍数也是满足方程的。所以我们只要将

φ

(

p

)

\varphi(p)

φ(p)质因子分解成

p

1

k

1

p

2

k

2

p

n

k

n

p_{1}^{k_{1}}p_{2}^{k_{2}}…p_{n}^{k_{n}}

p1k1p2k2pnkn
然后枚举每个质因子,判断是否存在

i

φ

(

p

)

p

j

1

(

m

o

d
  

p

)

i^{\frac{\varphi(p)}{p_{j}}}\equiv1(mod\;p)

ipjφ(p)1(modp)。若存在,说明阶比

φ

(

p

)

\varphi(p)

φ(p)小,则不是原根;反之,则是原根。

大力出奇迹,不愧是大力。
最后贴代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;

ll gcd(ll a,ll b)
{
    return b?gcd(b,a%b):a;
}

ll fpow(ll a,ll n,ll p)
{
    ll sum=1,base=a%p;
    while(n!=0)
    {
        if(n%2)sum=sum*base%p;
        base=base*base%p;
        n/=2;
    }
    return sum;
}

vector<ll> getPrimFac(ll n)
{
    vector<ll>fac;
    fac.clear();
    for(ll i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            fac.push_back(i);
            while(n%i==0)n/=i;
        }
    }
    if(n>1)fac.push_back(n);
    return fac;
}

bool hasRoot(ll n)
{
    if(n==2||n==4)return true;
    if(n<=1||n%4==0)return false;
    ll num=0;
    while(n%2==0)n/=2;
    for(ll i=3;i*i<=n;i++)
    {
        if(n%i==0)
        {
            num++;
            while(n%i==0)n/=i;
        }
    }
    if(n>1)num++;
    if(num==1)return true;
    return false;
}

ll getPhi(ll n)
{
    ll ans=n;
    for(ll 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 getRoot(ll n)
{
    if(!hasRoot(n))return -1;//不存在原根返回-1
    if(n==2)return 1;
    if(n==3)return 2;
    if(n==4)return 3;
    ll w=getPhi(n);
    vector<ll>fac=getPrimFac(w);
    for(ll i=2;i<w;i++)
    {
        if(gcd(i,n)!=1)continue;
        ll is=1;
        for(ll j=0;j<fac.size();j++)
        {
            if(fpow(i,w/fac[j],n)==1)is=0;
        }
        if(is)return i;
    }
    return -1;
}

int main()
{
    ll p;
    scanf("%lld",&p);
    printf("%lld\n",getRoot(p));
    return 0;
}


版权声明:本文为weixin_43785386原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>