要定义原根,先要引入数论中阶的概念。

阶的定义

a,mN+a,m\in\mathbb{N^+},且 ama\perp m,使 ax1(modm)a^x\equiv 1\pmod m 成立的最小正整数 xx,称为 aamm 的阶,记为 ordma\text{ord}_ma

阶的性质

说明:描述阶的性质时,默认 a,mN+a,m\in\mathbb{N^+},且 ama\bot m,即 ordma\mathrm{ord}_m a 存在。
性质1 an1(modm)a^n\equiv 1\pmod m 的充要条件为 ordman\mathrm{ord}_ma|n
证明ordma=x\mathrm{ord}_ma=x
首先证明充分性。设 n=pxn=px,其中 pN+p\in\mathbb{N^+}。则 $a^n\equiv a^{px}\equiv1\pmod m$;即 an1(modm)a^n\equiv 1\pmod m
接下来证明必要性。设 n=px+qn=px+q,其中 pN+p\in\mathbb{N^+} ,且 0q<x,qN0\le q<x,q\in\mathbb N。则 $a^n\equiv a^{px+q}\equiv a^q\equiv 1\pmod m$,得到 aq1(modm)a^q\equiv 1\pmod m,由于 xx 是满足 ax1(modm)a^x\equiv1\pmod m 的最小正整数,又 0q<x0\le q<x,所以 q=0q=0,故 xnx\mid n
证毕。
推论1 ordmaφ(m)\mathrm{ord}_ma\mid\varphi(m)
证明 由欧拉定理,aφ(m)1(modm)a^{\varphi(m)}\equiv1\pmod m,故 ordmaφ(m)\mathrm{ord}_ma\mid\varphi(m)
性质2bN+b\in\mathbb N^+,若 ab(modm)a\equiv b\pmod m,则 ordma=ordmb\text{ord}_ma=\text{ord}_mb
证明 首先 ab(modm)a\equiv b\pmod m,可以设 b=a+km,kZb=a+km,k\in\mathbb Z。则 gcd(b,m)=gcd(a+km,m)\gcd(b,m)=\gcd(a+km,m),由欧几里得算法 gcd(b,m)=gcd(m,a)=1\gcd(b,m)=\gcd(m,a)=1,故 bmb\bot m,所以 ordmb\mathrm{ord}_mb 存在。
接下来用反证法证明 ordma=ordmb\text{ord}_ma=\text{ord}_mb。假设 ordma=x\text{ord}_ma=xordmb=y\text{ord}_mb=y,且 xyx\ne y。则 ax(bkm)x1(modm)a^x\equiv(b-km)^x\equiv1\pmod m,将 (bkm)x(b-km)^x 用二项式定理展开,得到 bx1(modm)b^x\equiv1\pmod m。根据假设 ordmb=y\mathrm{ord}_mb=y,故 x>yx>y。然而,by(a+km)y1(modm)b^y\equiv(a+km)^y\equiv1\pmod m,将 (a+km)y(a+km)^y 用二项式定理展开,得到 ay1(modm)a^y\equiv1\pmod m;由于 ordma=x\mathrm{ord}_ma=x,故 x<yx<y,产生矛盾;所以,x=yx=y,即 ordma=ordmb\text{ord}_ma=\text{ord}_mb
证毕。
性质3p,qNp,q\in\mathbb Napaq(modm)a^p\equiv a^q\pmod m 的充要条件为 pq(modordma)p\equiv q\pmod {\text{ord}_ma}
证明 首先证明充分性。设 p=k1ordma+rp=k_1\mathrm{ord}_ma+rq=k2ordma+rq=k_2\mathrm{ord}_ma+r,其中 k1,k2,rNk_1,k_2,r\in\mathbb N,且 0r<ordma0\le r<\mathrm{ord}_ma。则 apak1ordma+rar(modm)a^p\equiv a^{k_1\mathrm{ord}_ma+r}\equiv a^r\pmod m,同理,aqar(modm)a^q\equiv a^r\pmod m,故 apaq(modm)a^p\equiv a^q\pmod m。充分性得证。
接下来证明必要性。不妨设 pqp\ge q,则 apq1(modm)a^{p-q}\equiv 1\pmod m。根据性质1ordampq\text{ord}_a m\mid p-q,所以 pq(modordma)p\equiv q\pmod {\text{ord}_ma}。必要性得证。
证毕。
性质4ordma=x\text{ord}_ma=x,则 1,a,a2,,ax11,a,a^2,\cdots,a^{x-1},模 mm 两两不同余。
证明 下面用反证法证明。
假设  i,jN\exists\ i,j\in\mathbb N0j<i<x0\le j<i<x,使得 aiaj(modm)a^i\equiv a^j\pmod m。故 aij1(modm)a^{i-j}\equiv1\pmod m,由阶的定义,ijxi-j\ge x,与 0j<i<x0\le j<i<x 矛盾。故假设错误。
证毕。
性质5bN+b\in\mathbb N^+,若 ab1(modm)ab\equiv1\pmod m,则 ordma=ordmb\text{ord}_ma=\text{ord}_mb
证明ordma=x\text{ord}_ma=xordmb=y\text{ord}_mb=y,则有 ax1(modm)a^x\equiv1\pmod mby1(modm)b^y\equiv 1\pmod m
axbxbx1(modm)a^xb^x\equiv b^x\equiv1\pmod m,由阶的定义 xyx\ge yaybyay1a^yb^y\equiv a^y\equiv 1,由阶的定义,xyx\le y。所以,x=yx=y
证毕。
性质6x=ordmax=\text{ord}_ma,有 tN+t\in\mathbb N^+ordmat=xgcd(t,x)\text{ord}_ma^t=\frac{x}{\gcd(t,x)}
证明ordmat=k\text{ord}_ma^t=k,根据阶的定义,有 akt1(modm)a^{kt}\equiv1\pmod m
性质1xktx\mid kt,故 xgcd(t,x)tgcd(t,x)k\frac{x}{\gcd(t,x)}\mid\frac{t}{\gcd(t,x)}k 。根据最大公约数的性质,xgcd(t,x)tgcd(t,x)\frac{x}{\gcd(t,x)}\bot\frac{t}{\gcd(t,x)},所以 xgcd(t,x)k\frac{x}{\gcd(t,x)}\mid k
根据阶的定义,kk 为满足 xgcd(t,x)k\frac{x}{\gcd(t,x)}\mid k 的最小正整数,故 k=xgcd(t,x)k=\frac{x}{\gcd(t,x)}
证毕。
性质7wN+w\in\mathbb N^+,若 wmw\mid m,则 ordwaordma\text{ord}_wa\mid \text{ord}_ma
证明 由阶的定义,aordma1(modm)a^{\mathrm{ord}_ma}\equiv1\pmod m;因此,aordma=km+1a^{\mathrm{ord}_ma}=km+1kNk\in\mathbb N。因为 wmw\mid m,所以 aordma1(modw)a^{\mathrm{ord}_ma}\equiv1\pmod w。根据性质1ordwaordma\text{ord}_wa\mid \text{ord}_ma
证毕。
性质8nN+n\in\mathbb N^+。若 mn,anm\bot n,a\bot n,则 $\text{ord}_{mn}a=\text{lcm}(\text{ord}_{m}a,\text{ord}_{n}a)$。
证明 令 $x=\text{ord}_{mn}a$,$y=\text{lcm}(\text{ord}_{m}a,\text{ord}_{n}a)$。
根据阶的定义,ax1(modmn)a^x\equiv1\pmod{mn},于是有 ax=kmn+1a^x=kmn+1kMk\in\mathbb M;故 ax1(modm)a^x\equiv 1\pmod {m}ax1(modn)a^x\equiv 1\pmod {n}。由性质1,$ \text{ord}_ma\mid x$ 且 ordnax\text{ord}_na\mid x,故 $\text{lcm}(\text{ord}_{m}a,\text{ord}_{n}a)\mid x$,即 $y\mid x$。
由最小公倍数的定义,有 $\mathrm{ord}_{m}a\mid y$,$\text{ord}_{n}a\mid y$。根据性质1,有 ay1(modm)a^y\equiv1\pmod may1(modn)a^y\equiv1\pmod n;令 ay=k1m+1=k2n+1a^y=k_1m+1=k_2n+1k1,k2Nk_1,k_2\in\mathbb N,即 k1m=k2nk_1m=k_2n。因为 mnm\bot n,故 k1=kn,k2=kmk_1=kn,k_2=kmkNk\in\mathbb N,所以 ay1(modmn)a^y\equiv1\pmod{mn}。再次根据性质1,有 $\mathrm{ord}_{mn}a\mid y$,即 xyx|y
综上所述,x=yx=y,即 $\text{ord}_{mn}a=\text{lcm}(\text{ord}_{m}a,\text{ord}_{n}a)$。
证毕。
性质9bN+b\in\mathbb N^+,若 bmb\bot mordmaordmb\mathrm{ord}_ma\bot \mathrm{ord}_mb,则 ordmab=ordma×ordmb\mathrm{ord}_mab=\mathrm{ord}_ma\times \mathrm{ord}_mb
证明x=ordmax=\mathrm{ord}_may=ordmby=\mathrm{ord}_mbz=ordmabz=\mathrm{ord}_mab。由阶的定义,有 ax1(modm)a^x\equiv1\pmod mby1(modm)b^y\equiv1\pmod m(ab)z1(modm)(ab)^z\equiv1\pmod m
(ab)z1(modm)(ab)^z\equiv1\pmod m,得 az1(modm)a^z\equiv1\pmod mbz1(modm)b^z\equiv 1\pmod m。根据性质1xzx\mid zyzy\mid z,故 lcm(x,y)z\mathrm{lcm}(x,y)\mid z。因为 ordmaordmb\mathrm{ord}_ma\bot \mathrm{ord}_mb,即 xyx\bot y;所以 lcm(x,y)=xy\mathrm{lcm}(x,y)=xy,即 xyzxy\mid z
因为 x=ordmax=\mathrm{ord}_may=ordmby=\mathrm{ord}_mb,所以 (ab)xy1(modm)(ab)^{xy}\equiv 1\pmod m。根据性质1zxyz\mid xy
综上所述,z=xyz=xy,即 ordmab=ordma×ordmb\mathrm{ord}_mab=\mathrm{ord}_ma\times \mathrm{ord}_mb
证毕。

原根

原根的定义

g,mN+g,m\in\mathbb N^+,且 gmg\bot m;若 ordmg=φ(m)\mathrm{ord}_mg=\varphi(m),则称 gg 是模 mm 的原根。

原根存在定理

不加证明地给出:模 m{\displaystyle m} 有原根的充要条件是 m=2,4,pk,2pkm=2,4,p^k,2p^k,其中 pp 是奇素数,kk 是任意正整数。

原根判定定理

不加证明地给出:若 gg 为模 mm 的原根,则对于任意 φ(m)\varphi(m) 的质因子 pp,必有 gφ(m)p≢1(modm)g^{\frac{\varphi(m)}{p}}\not\equiv 1 \pmod m

求所有原根

定理gg 为模 mm 的原根,则集合 S={gs1sφ(m),sφ(m)}S=\{g^{s} \mid 1 \leq s \leq \varphi(m),s\bot\varphi(m)\} 给出模 mm 的全部原根。模 mm 的原根有 φ(φ(m))\varphi(\varphi(m)) 个。
略证 由原根的判定定理,对于任意 φ(m)\varphi(m) 的质因子 pp,有 gφ(m)p≢1(modm)g^{\frac{\varphi(m)}{p}}\not\equiv 1 \pmod m;因此,(gs)φ(m)p(gφ(m))sp(modm)\left(g^s\right)^{\frac{\varphi(m)}{p}}\equiv \left(g^{\varphi(m)}\right)^{\frac{s}{p}}\pmod m。若 gcd(s,φ(m))>1\gcd(s,\varphi(m))>1,则存在一个 pp,使得 psp\mid s;此时,(gφ(m))spgkφ(m)(modm)\left(g^{\varphi(m)}\right)^{\frac{s}{p}}\equiv g^{k\varphi(m)}\pmod mkN+k\in\mathbb N^+;根据欧拉定理 gφ(m)1(modm)g^{\varphi(m)}\equiv1\pmod m。因此,当且仅当 sφ(m)s\bot\varphi(m)gsg^s 才为模 mm 的原根。
s>φ(m)s>\varphi(m),由扩展欧拉定理,则 gsgsmodφ(m)(modm)g^s\equiv g^{s\bmod \varphi(m)}\pmod m,转化为 1sφ(m)1\le s\le \varphi(m) 的问题。
根据欧拉函数定义,满足条件 1sφ(m),sφ(m)1\leq s \leq \varphi(m),s\bot\varphi(m)ssφ(φ(m))\varphi(\varphi(m)) 个。根据阶的性质4,这 φ(φ(m))\varphi(\varphi(m)) 个原根模 mm 两两不同余。
可以证明,最小原根是不大于 m4\sqrt[4]{m} 级别的。因此,不妨枚举 [1,m4][1,\sqrt[4]{m}] 的整数,得到最小原根 gg,这样的时间是可以接受的;接着,再枚举 gsg^s 的指数 ss,若 ssφ(m)\varphi(m) 互质,则 gsmodmg^s\bmod m 为一个原根。

51Nod 1135 原根 \looparrowright

给出一个质数 PP,找出 PP 最小的原根。

输入

输入一个质数 PP(3P109)(3\le P \le 10^9)

输出

输出 PP 最小的原根。

输入样例

3

输出样例

2

分析

11 开始枚举可能的原根,根据原根判定定理检验:对于任意 φ(P)\varphi(P) 的质因子 pp,有 gφ(P)p≢1(modP)g^{\frac{\varphi(P)}{p}}\not\equiv 1 \pmod P
由欧拉函数的性质,PP 为质数,故 φ(P)=P1\varphi(P)=P-1

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include<iostream>
#include<vector>
#define ll long long
using namespace std;
vector<ll>prime_factor;
ll P;
//--------------------------------
//分解质因数
void divide(ll x)
{
ll i;
for(i=2;i*i<=x;i++)
{
if(x%i==0)
{
prime_factor.push_back(i);
while(x%i==0) x/=i;
}
}
if(x>1) prime_factor.push_back(i);
}
//-----------------------------------
//-----------------------------------
//若P为质数
//φ(P)=P-1
inline ll phi(ll p) {return p-1;}
//-----------------------------------
//-----------------------------------
//快速幂
inline ll qpow_mod(ll a,ll b,ll mod)
{
ll res=1;
while(b)
{
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
//------------------------------------
int main()
{
cin>>P;
divide(phi(P));
ll i,j;
for(i=1;;i++)//枚举
{
bool is=1;
//遍历P-1的所有质因子
for(j=0;j<prime_factor.size();j++)
{
if(qpow_mod(i,phi(P)/prime_factor[j],P)==1)
{
is=0;
break;
}
}
if(is)//满足条件
{
cout<<i<<endl;
return 0;
}
}
}

HDU Primitive Roots 4992 \looparrowright

Problem Description

We say that integer xx, 0<x<n0 < x < n, is a primitive root modulo nn if and only if the minimum positive integer yy which makes xy=1(modn)x^y = 1 \pmod n true is φ(n)φ(n) . Here φ(n)φ(n) is an arithmetic function that counts the totatives of nn, that is, the positive integers less than or equal to nn that are relatively prime to nn. Write a program which given any positive integer nn(2n<1000000)( 2 \le n < 1000000), outputs all primitive roots of nn in ascending order.

Input

Multi test cases.
Each line of the input contains a positive integer nn. Input is terminated by the end-of-file separator.

Output

For each nn, outputs all primitive roots of nn in ascending order in a single line, if there is no primitive root for nn just print 1-1 in a single line.

Sample Input

4
25

Sample Output

3
2 3 8 12 13 17 22 23

Idea

首先根据原根存在定理判断原根是否存在。
若原根存在,枚举 [1,n4][1,\sqrt[4]{n}] 的整数,得到最小原根 gg;接着,再枚举 gsg^s 的指数 ss,若 ssφ(n)\varphi(n) 互质,则 gsmodng^s\bmod n 为一个原根;若找到的原根已经达到 φ(φ(n))\varphi(\varphi(n)) 个,就可以停止枚举。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include<cstdio>
#include<vector>
#include<algorithm>
#define ll long long
#define N 1000002
using namespace std;
int cnt;//质数个数
bool vis[N];//vis[i]=1表示i为合数
int prime[N>>1];//质数
int phi[N];//欧拉函数
vector<int>prime_factor;//质因子
vector<int>ans;//所有模n的原根
//-------------------------------------------------------
//欧拉筛线性得到欧拉函数
void get_phi(int n)
{
phi[1]=1;
int i,j;
for(i=2;i<=n;i++)
{
if(!vis[i])
{
phi[i]=i-1;
prime[++cnt]=i;
}
for(j=1;j<=cnt&&i*prime[j]<=n;j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
}
//-------------------------------------------------------
//-------------------------------------------------------
//快速幂
inline int qpow_mod(ll a,int b,int mod)
{
ll res=1;
while(b)
{
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
//-------------------------------------------------------
//-------------------------------------------------------
//分解质因数
inline void divide(int x)
{
int i;
for(i=2;i*i<=x;i++)
{
if(x%i==0)
{
prime_factor.push_back(i);
while(x%i==0) x/=i;
}
}
if(x>1) prime_factor.push_back(x);
}
//-------------------------------------------------------
//-------------------------------------------------------
//利用原根存在定理
bool exist(int n)
{
if(n==2||n==4) return 1;
if(n%2==0) n/=2;//猜测为奇素数幂的二倍
int i;
//检验是否为奇素数的幂
for(i=2;prime[i]<=n;i++)
{
if(n%prime[i]==0)
{
while(n%prime[i]==0) n/=prime[i];
//若n存在原根
//i为唯一质因子
return n==1;
}
}
return 0;
}
//-------------------------------------------------------
//-------------------------------------------------------
int main()
{
get_phi(1000000);//预处理1~1000000的欧拉函数
int n;
while(~scanf("%intd",&n))
{
//首先检验n是否存在原根
if(exist(n))
{
prime_factor.clear();
ans.clear();
//对phi[n]分解质因数
divide(phi[n]);
int i,j;
int g;
//---------------------------------------------------------
//找到最小原根g
for(i=1;;i++)
{
bool is=1;
if(__gcd(i,n)!=1) continue;//i不存在模n的阶
for(j=0;j<prime_factor.size();j++)
{
//--------------------------------------------------
//原根判定
//对phi[n]的所有质因子p
//i^(phi[n]/p)%n!=1;
if(qpow_mod(i,phi[n]/prime_factor[j],n)==1)
{
is=0;
break;
}
//--------------------------------------------------
}
if(is)//找到最小原根
{
g=i;
break;
}
}
//---------------------------------------------------------
//---------------------------------------------------------
//枚举指数s
//若s与phi[n]互质
//g^s为原根
int s;
ll power=1;
for(s=1;ans.size()<phi[phi[n]];s++)
{
power=power*g%n;
if(__gcd(phi[n],s)==1) ans.push_back(power);
}
sort(ans.begin(),ans.end());
//---------------------------------------------------------
for(i=0;i<ans.size();i++)
{
if(i) putchar(' ');
printf("%d",ans[i]);
}
putchar('\n');
}
else puts("-1");
}
return 0;
}