数论之阶与原根讲解

ぐ巨炮叔叔 提交于 2020-01-28 19:33:34

前言:

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

提要:

为了减少后面的阅读障碍,先简单介绍一下欧拉函数φ(x)\varphi(x),主要部分后面放积性函数那介绍。(ps:书上符号写的是ϕ(x)\phi(x),但网上写的是φ(x)\varphi(x),不过这不重要)
欧拉函数φ(x)\varphi(x)的函数值是,小于xx且与xx互质的正整数的个数。
比如φ(6)=2\varphi(6)=2,因为小于66的正整数中,仅有1155与其互质。
容易发现,pp为素数时,有φ(x)=p1\varphi(x)=p-1
还有欧拉定理:若gcd(a,n)=1gcd(a,n)=1,则aφ(n)1(mod  p)a^{\varphi(n)}\equiv1(mod\;p)
 
差不多先这些,开始正文。
 

整数的阶:

什么是阶?
aann是互素的整数,a0,n>0a\neq 0,n>0,使得ax1(mod  n)a^{x}\equiv1(mod\;n)成立的最小正整数xx称为aann的阶,符号表示为ordnaord_{n}a
 
比如要求2277的阶,我们一一列举,
212(mod  7)224(mod  7)231(mod  7)2^{1}\equiv2(mod\;7),2^{2}\equiv4(mod\;7),2^{3}\equiv1(mod\;7)
那么我们称2277的阶就是33,记为ord72=3ord_{7}2=3
 
现在我们观察方程ax1(mod  n)a^{x}\equiv1(mod\;n)
那么显然根据欧拉定理,我们可以知道φ(n)\varphi(n)是方程的一个解,但它未必是最小的,所以不一定是阶,而当φ(n)\varphi(n)aann的阶时,我们称aann的一个原根,这个放后面介绍。

现在继续来讲阶。
 
定理一:若gcd(a,n)=1gcd(a,n)=1,则x0x_{0}是方程ax1(mod  n)a^{x}\equiv1(mod\;n)的一个解的充要条件是ordnaxord_{n}a|x。(其中|是整除符号,表示ordnaord_{n}a整除xx)
这个必要性很好证明,既然aordna1(mod  n)a^{ord_{n}a}\equiv1(mod\;n),那ak×ordna1(mod  n)a^{k\times ord_{n}a}\equiv1(mod\;n)当然也成立。
然后充分性,假设存在x1x1不整除x0x_{0}且满足方程,令x1=k×ordna+dx_{1}=k\times ord_{n}a+d(其中dd不整除ordnaord_{n}a)满足方程,那么dd一定比ordnaord_{n}a小,且满足ad1(mod  n)a^{d}\equiv1(mod\;n),那它才是原根嘛。
这样就证好了。

定理二:若gcd(a,n)=1gcd(a,n)=1,则ordnaord_{n}a能整除φ(n)\varphi(n)
前面看下来应该也能想到,且由定理一发现显然嘛。
这时候我们容易想到一个o(nlog)o(\sqrt{n} log)求阶的办法,因为nn的阶一定是φ(n)\varphi(n)的因子,所以可以暴力枚举其因子,再看看是不是满足条件。

定理三:若gcd(a,n)=1gcd(a,n)=1,则aiaj(mod  n)a^i\equiv a^j(mod\;n)的充要条件是ij(mod  ordna)i\equiv j(mod\;ord_{n}a)
定理比较重要,自己意会一下。

定理四:若ordna=tord_{n}a=t,且uu为正整数,则有ordn(au)=tgcd(t,u)ord_{n}(a^{u})=\frac{t}{gcd(t,u)}
打个比方体会一下,231(mod  7)2^3\equiv1(mod\;7),那么就有811(mod  7)8^1\equiv1(mod\;7)。其实就是这个33的因子,这样想就容易理解多了吧。
 
 

原根:

aann的阶为φ(n)\varphi(n),也就是说当且仅当xxφ(n)\varphi(n)的倍数,使得ax1(mod  n)a^{x}\equiv1(mod\;n)成立,此时称aann的原根
 
那么知道了nn的原根aa后,有什么好处呢,可以举一个例子。
我们举998244353的原根3, 我们举一个素数77的一个原根33,然后列举33的幂次模77
313(mod  7)322(mod  7)336(mod  7)344(mod  7)355(mod  7)361(mod  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)
然后发现这些余数构成了一个模77的完全剩余系1,2,3,4,5,61,2,3,4,5,6,也就是对于任意aa,都可以找到x0x_{0}使得3x0a(mod  7)3^{x_{0}}\equiv a(mod\;7)
这是素数的情况,现在我们来康康非素数的情况,举1818的一个原根55。然后列举55的幂次模1818
515(mod  18)5^{1}\equiv5(mod\;18),
527(mod  18)5^{2}\equiv7(mod\;18),
5317(mod  18)5^{3}\equiv17(mod\;18),
5413(mod  18)5^{4}\equiv13(mod\;18),
5511(mod  18)5^{5}\equiv11(mod\;18),
561(mod  18)5^{6}\equiv1(mod\;18)。
575(mod  18)5^{7}\equiv5(mod\;18),
587(mod  18)5^{8}\equiv7(mod\;18),
5917(mod  18)5^{9}\equiv17(mod\;18),
51013(mod  18)5^{10}\equiv13(mod\;18),
51111(mod  18)5^{11}\equiv11(mod\;18),
5121(mod  18)5^{12}\equiv1(mod\;18)。
5135(mod  18)5^{13}\equiv5(mod\;18),
5147(mod  18)5^{14}\equiv7(mod\;18),
51517(mod  18)5^{15}\equiv17(mod\;18),
51613(mod  18)5^{16}\equiv13(mod\;18),
51711(mod  18)5^{17}\equiv11(mod\;18),
5181(mod  18)5^{18}\equiv1(mod\;18)。
很容易发现以66个为一组,那这个66是什么呢?
其实是φ(18)=6\varphi(18)=6。然后出现的数字1,5,7,11,13,171,5,7,11,13,17,正是与1818互质的那66个数啊。
那么前面素数的情况也说得通了。
所以我们就可以得到,
定理一:若gcd(a,n)=1gcd(a,n)=1,则a1,a2,,aφ(n)a^{1},a^{2},……,a^{\varphi(n)}构成模nn的既约剩余系。
大概懂了就不证明了。
而当pp为素数时,我们就可以将求解方程x5a(mod  p)x^{5}\equiv a(mod\;p)的问题代换为求解g5xa(mod  p)g^{5x}\equiv a(mod\;p),其中ggpp的原根,因为gg的幂次是模nn的完全剩余系,所以可以用gxg^{x}来代换xx,这样我们只要求出新方程的x0x_{0},那么原方程的解就可以求出来了。
 
下一个,
定理二:如果一个数nn有原根,那么他有多少个不同余的原根,
答案是φ(φ(n))\varphi(\varphi(n))个。
伪证明:由前面阶那里的定理四,我们可以知道ordn(au)=tgcd(t,u)ord_{n}(a^{u})=\frac{t}{gcd(t,u)},那么当aann的原根时,就有ordna=φ(n)ord_{n}a=\varphi(n)
于是我们得到,ordn(au)=φ(n)gcd(φ(n),u)ord_{n}(a^{u})=\frac{\varphi(n)}{gcd(\varphi(n),u)}
所以要使ordn(au)ord_{n}(a^{u})等于φ(n)\varphi(n),就要满足gcd(φ(n),u)gcd(\varphi(n),u),在11φ(n)1\varphi(n)-1范围里自然就有φ(φ(n))\varphi(\varphi(n))个满足条件的。

吃饭去了,回来再写。

现在研究哪些数是有原根的,也就是原根的存在性
因为刚吃了饭,我懒了。
先证明素数都是有原根的。
再证明奇素数的幂都是有原根的。
然后讨论关于22的幂次,发现2244是有原根的,其他22的幂次都没有原根。
然后再发现22乘上奇素数的幂也是有原根的。
最后再证明剩下的都没有原根。
于是,得出结论:
定理三:2244,和奇素数的正整数幂次pkp^{k},以及22乘上奇素数的正整数幂次2pk2p^{k}都是有原根的。
 
 
最后,再研究一下怎么求pp的原根。传送门
先给出一种暴力的解法。(没有第二种了)
先判断有无原根。
22的原根是1133的原根是2,44的原根是33直接特判掉。
然后我们暴力枚举[2,p1][2,p-1],再判断它是不是pp的原根,枚举的时候当然还要保证与模数互质。
至于要判断ii是不是pp的原根,只要看是否存在x0x_{0}φ(p)\varphi(p)小,且满足ix01(mod  p)i^{x_{0}}\equiv 1(mod\;p)
但是我们不至于再去一个一个枚举x0x_{0},因为我们知道它的阶是满足方程的,而阶的倍数也是满足方程的。所以我们只要将φ(p)\varphi(p)质因子分解成p1k1p2k2pnknp_{1}^{k_{1}}p_{2}^{k_{2}}…p_{n}^{k_{n}}
然后枚举每个质因子,判断是否存在iφ(p)pj1(mod  p)i^{\frac{\varphi(p)}{p_{j}}}\equiv1(mod\;p)。若存在,说明阶比φ(p)\varphi(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;
}

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!