原根学习笔记

原根学习笔记

原根

这是一个又臭又长的内容。

拉格朗日定理:设 p 为素数,对于模 p 意义下的整系数多项式

f(x)=anxn+an1xn1++a0(pan)

的同余方程 f(x)0(modp) 在模 p 意义下至多有 n 个不同解。

证明:使用归纳法,对于 n=0 时,由于 pa0,所以 f(x)0(modp) 无解,定理对 n=0 的多项式 f(0) 都成立。

若命题对于 n<x 均成立,采用反证法,假设当 n=x 时有至少 x+1 个解 x0,x1,,xn。不妨设 f(x)f(x0)=(xx0)g(x),则 g(x) 在模 p 意义下是一个至多 n1 次的多项式。因为当 x=x1,x2,,xn 时,f(x)0(modp),所以

(xix0)g(xi)f(xi)f(x0)=f(xi)0(modp)

从而 g(x)0(modp) 至少有 n 个根,与归纳假设矛盾。

所以定理对 n 次多项式也成立,得证。

:由欧拉定理可知,对 aZ,mN,若 gcd(a,m)=1,则

aφ(m)1(modm)

因此满足同余式 an1(modm) 的最小正整数 n 存在,这个 n 称作 am 的阶,记作 δm(a)

原根:设 mN,aZ。若 gcd(a,m)=1,且 δm(a)=φ(m),则称 a 为模 m 的原根。

关于阶有一个较为显然的性质:

an1(modm),则 δm(a)n

证明:对 n 除以 δm(a) 作带余除法,设

n=δm(a)q+r,0r<δm(a)

r>0,则

arar(aδm(a))qan1(modm)

这与 δm(a) 的最小性矛盾。故 r=0,即 δm(a)n

关于阶还有两个重要的性质:

性质 1:设 mN,a,bZ,gcd(a,m)=gcd(b,m)=1,则

δm(ab)=δm(a)δm(b)

的充要条件是 gcd(δm(a),δm(b))=1

证明:必要性:有 aδm(a)1(modm)bδm(b)1(modm),可知

(ab)lcm(δm(a),δm(b))1(modm)

由前面所述的性质,有

δm(ab)lcm(δm(a),δm(b))

有由于 δm(ab)=δm(a)δm(b),所以

δm(a)δm(b)lcm(δm(a),δm(b))

所以 gcd(δm(a),δm(b))=1

充分性:由 (ab)δm(ab)1(modm) 可知

1(ab)δm(ab)δm(b)aδm(ab)(modm)

δm(a)δm(ab)δm(b)。结合 gcd(δm(a),δm(b))=1 即得

δm(a)δm(ab)

对称地,可得

δm(b)δm(ab)

所以

δm(a)δm(b)δm(ab)

另一方面,有

(ab)δm(a)δm(b)(aδm(a))δm(b)(bδm(b))δm(a)1(modm)

δm(ab)δm(a)δm(b)

综合即可得到 δm(ab)=δm(a)δm(b)

性质 2:设 kN,mN,aZ,gcd(a,m)=1,则

δm(ak)=δm(a)gcd(δm(a),k)

证明:注意到

akδm(ak)=(ak)mδ(ak)1(modm)δm(a)kδm(ak)δm(a)gcd(δm(a),k)δm(ak)

另一方面,由 aδm(a)1(modm) 可知

(ak)δm(a)gcd(δm(a),k)=(aδm(a))kgcd(δm(a),k)1(modm)

所以

δm(ak)δm(a)gcd(δm(a),k)

综合可得 δm(a)=δm(a)gcd(δm(a),k)

接下来讨论什么样的 m 存在原根。

首先,对于 m=1,2,4,显然存在原根。

定理 1:对于奇素数 pp 存在原根。

证明:先证明一个引理:

引理:设 ab 是与 p 互素的两个整数,则存在 cZ 使得 δp(c)=lcm(δp(a),δp(b))

证明:记 r=δm(a),t=δm(b),设它们的标准分解为(只要求 max(αi,βi)>0

r=i=1spiαi,t=i=1spiβi

l 为所有 αiβipiαi 的乘积,m 为所有 βi<αipiβi 的乘积。记r=lx,t=my,则 gcd(x,y)=1,lcm(r,t)=xy

由性质 2δp(al)=x,δp(bm)=y,则由性质 1δp(albm)=xy=lcm(δp(a),δp(b)),取 c=albm 即可。

1p1 依次两两使用引理,可知存在 gZ 使得

δp(g)=lcm(δp(1),δp(2),,δp(p1))

这表明 δp(j)δp(g),所以 j=1,2,,p1 都是同余方程

xδp(g)1(modp)

的根。有拉格朗日定理可知,δp(g)p1。又由费马小定理,易知 δp(g)p1,所以 δp(g)=p1=φ(p)。所以 gp 的原根。

定理 2:对于奇素数 pαNpα 有原根。

证明:先证明一个引理。

引理:存在模 p 的原根 g,使得 gp11(modp2)

证明:事实上,仍取模 p 的原根 g,若 g 不满足条件,我们认定 g+p 满足条件。易知 g+p 也是模 p 的原根。

于是有

(g+p)p1gp1+(p1)pgp21pgp21(modp2)

接着,我们证明若 g 是一个满足引理条件的原根,则对于任意 αNg 是模 pα 的原根。

首先证明下面的结论:对于任意 βN,都可设

gφ(pβ)=1+pβkβ

不难发现当 β=1 时结论成立,现设上式对 β 成立,则

gφ(pβ+1)=(gφ(pβ))p=(1+pβkβ)p1+pβ+1kβ

结合 pkβ 可知结论成立。

所以命题对 βN 都成立。

其次,记 δ=δpα(g),则有欧拉定理,可知 δpα1(p1)

而由 g 为模 p 的原根,及 gδ1(modpα) 可知 (p1)δ

所以可设 δ=pβ1(p1)(1βα)。利用之前的结论可知

gφ(pβ)1(modpβ+1)gδ1(modpβ+1)

结合 gδ1(modpα) 可知 βα。所以 β=α,即

δpα(g)=pα1(p1)=φ(pα)

从而 gpα 的原根。

定理 3:对于奇素数 pαN2pα 有原根。

证明:设 g 是模 pα 的原根,则 g+pα 也是模 pα 的原根。

gg+pα 中有一个是奇数,设其为 G,则 gcd(G,2pα)=1

由欧拉定理,δ2pα(G)φ(2pα)

Gδ2pα(G)1(mod2pα),故 Gδ2pα(G)1(modpα)

利用 G 为模 pα 的原根可知 φ(pα)δ2pα(G)

结合 φ(pα)=φ(2pα) 可知 G 为模 2pα 的原根。

定理 4:对于 m{1,2,4,pα,2pα},则对于任意 aZ,都有 δma<φ(m),即模 m 的原根不存在。

证明:对于 m=2α,αN,α3,则对于任意奇数 a=2k+1

a2α2=(2k+1)2α21+2α2(2k)+2α1(2α21)k21+2α1(k+(2α21)k)1(mod2α)

m 不是 2 的次幂,则设 m=rt 满足 2<r<t,gcd(r,t)=1。则由欧拉定理可知

aφ(r)1(modr),aφ(t)1(modt)

n>2 时,φ(n) 为偶数,所以

aφ(r)φ(t)21(modrt)

所以 δm(a)φ(r)φ(t)2=φ(rt)2=φ(m)2<φ(m)


上述定理阐述了原根的充要条件,即除了 1,2,4,pα,2pα 以外,其他的数都没有原根。于是我们可以与处理素数即其幂次,O(1) 判断是否有原根。

如果一个数有原根,可以先求出其最小原根。事实上,m 的最小原根是不多于 m14 级别的。根据这个结论,我们可以直接从小到大枚举。根据原根的定义,若 g 为模 m 的原根,则对于 φ(m) 的任意素因数 p,必有

gφ(m)p1(modm)

同时,只要满足如上条件的 g 一定是原根。于是我们可以与处理出 φ(m) 的所有质因数,通过快速幂来判断。

假如找到了一个原根 g,不难证明对于所有 gcd(x,φ(m))=1xgx 均为原根,所以模 m 的原根有 φ(φ(m)) 个,所以我们可以在找到 g 后再枚举找出所有 m 的原根。

指标

对于 m 的原根 g,那么当 gra(modm)(r<m) 时,记 γ(a)=r。并且有以下性质

  1. ab(modm)γ(a)γ(b)(modφ(m))
  2. γ(ab)γ(a)+γ(b)(modφ(m))
  3. γ(an)nγ(a)(modφ(m))

求解的方法也很简单,用 bsgs 即可。

代码

#include <bits/stdc++.h>
using namespace std;
#define ll long long

const int N=1e6+5;

int T,n,d,tot,cnt,sum;
int p[N],phi[N],fc[N];
ll ans[N];
bool rt[N],vis[N];

void Euler(int x){
    phi[1]=1;
    for(int i=2;i<=x;i++){
        if(!vis[i]){
            p[++tot]=i;
            phi[i]=i-1;
        }
        for(int j=1;p[j]<=x/i;j++){
            vis[i*p[j]]=true;
            if(i%p[j]==0){
                phi[i*p[j]]=phi[i]*p[j];
                break;
            }
            phi[i*p[j]]=phi[i]*(p[j]-1);
        }
    }
    rt[1]=rt[2]=rt[4]=true;
    for(int i=2;i<=tot;i++){
        for(int j=1;j<=x/p[i];j*=p[i])rt[j*p[i]]=true;
        for(int j=2;j<=x/p[i];j*=p[i])rt[j*p[i]]=true;
    }
    return ;
}

int Gcd(int a,int b){
    return b==0?a:Gcd(b,a%b);
}

ll QuickPow(ll a,int b,int p){
    ll res=1;
    while(b>0){
        if((b&1)==1)res=res*a%p;
        a=a*a%p;
        b>>=1;
    }
    return res;
}

void Fac(int x){
    cnt=0;
    for(int i=1;p[i]<=x/p[i];i++){
        if(p[i]>x)break ;
        if(x%p[i]==0){
            fc[++cnt]=p[i];
            while(x%p[i]==0)x/=p[i];
        }
    }
    if(x>1)fc[++cnt]=x;
    return ;
}

bool Check(int x,int p){
    if(QuickPow(x,phi[p],p)!=1)return false;
    for(int i=1;i<=cnt;i++){
        if(QuickPow(x,phi[p]/fc[i],p)==1)return false;
    }
    return true;
}//检验是否是原根

int FindRt(int x){
    for(int i=1;i<x;i++){
        if(Check(i,x))return i;
    }
    return 0;
}//找最小原根

void GetRt(int x,int p){
    ll res=1;
    sum=0;
    for(int i=1;i<=phi[p];i++){
        res=res*x%p;
        if(Gcd(i,phi[p])==1)ans[++sum]=res;
    }
    return ;
}//处理所有原根

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>T;
    Euler(N-5);//预处理质数、phi、有无原根
    while(T--){
        cin>>n>>d;
        if(rt[n]){
            Fac(phi[n]);//预处理质因数
            GetRt(FindRt(n),n);//找最小原根后找所有原根
            sort(ans+1,ans+sum+1);
            cout<<sum<<"\n";
            for(int i=1;i<=sum/d;i++)cout<<ans[i*d]<<" ";
            cout<<"\n";
        }else cout<<"0\n\n";//直接判断没有原根
    }
    return 0;
}
posted @   DycIsMyName  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示