原根

1 阶

1.1 定义

由欧拉定理可知,对于 aZ,mN+,如果 gcd(a,m)=1,则 aφ(m)1(modm)

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

1.2 性质

只要扯到数学性质和证明这部分内容就会极其恶臭。

性质 1:

a,a2,aδm(a)m 两两不同余。

证明:考虑反证。若存在 i,j 使得 aiaj(modm),则 a|ij|1(modm)。但是 δm(a) 是最小的满足 an1(modm)n,所以 |ij| 不可能满足该条件,矛盾,故原命题成立。

性质 2:

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

证明:设 n=kδm(a)+r,0r<δm(a),那么会有:

anakδm(a)+rakδm(a)×arar1(modm)

所以 ar1,但是 δm(a) 是满足 an1(modm) 的最小 n,所以 r 只可能等于 0,于是 δm(a)n

据此性质可有以下推论:若 apaq(modm),则 pq(modδm(a))

性质 3:

mN+a,bZgcd(a,m)=gcd(b,m)=1,则

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

的充要条件是

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

证明:

  • 必要性:

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

    根据性质二可得 δm(ab)lcm(δm(a),δm(b)),故 δm(a)δm(b)lcm(δm(a),δm(b)),因此 gcd(δm(a),δm(b))=1

  • 充分性:

    (ab)δm(ab)1(modm) 可得 (ab)δm(ab)×δm(b)aδm(ab)×δm(b)1(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)

性质 4:

kN,mN+,aZ,gcd(a,m)=1,则

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

证明:

(ak)δm(ak)1(modm) 可得 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))akgcd(δm(a),k)1(modm)。故 δm(ak)δm(a)gcd(δm(a),k)

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

2 原根

2.1 定义

mN+,gZ,若 gcd(m,g)=1,且 δm(g)=φ(m),称 g 为模 m 的原根。

m 为质数时,由阶的性质 1 可得,此时 gi(0<i<m)m 两两不同余。

2.2 原根判定定理

mN+,gZ,若 gcd(m,g)=1,则 g 为模 m 的原根的充要条件是,对于 φ(m) 的任意一个质因子 p,都满足 gφ(m)p1(modm)

证明:必要性显然,如果存在则说明 δm(g) 不是最小的 n,矛盾。

充分性考虑反证,假设存在一个 p,满足对于 φ(m) 的任意一个质因子 p,都满足 gφ(m)p1(modm),但是 g 不是 m 的原根。那么由于 gφ(m)1(modm),会有 δm(g)φ(m)

由于 g 不是 m 的原根,所以 δm(g)φ(m),所以一定存在一个 φ(m) 的质因子 p 使得 δm(g)φ(m)p,而这个质因子 p 就满足 gφ(m)p1(modm),与条件矛盾。必要性得证。

2.3 原根个数

若一个数 m 有原根,则它的原根个数为 φ(φ(m)) 个。

证明:

m 有原根 g,根据阶的性质 4 可得:

δm(gk)=δm(g)gcd(δm(g),k)=φ(m)gcd(φ(m),k)

所以如果 gcd(φ(m),k)=1,就会有 δm(gk)=φ(m),此时 gk 也是 m 的原根。 而这样的 kφ(φ(m)) 个,所以原根就有 φ(φ(m)) 个。

2.4 原根存在定理

一个数 m 存在原根,当且仅当 m=2,4,pk,2pk,其中 p 是奇质数。

这个定理可以帮助我们用于判定一个数是否有原根,其证明较为复杂,在此不作详细叙述,可以看OI Wiki上的证明。

2.5 求原根

有了上面三个定理,找原根其实并不困难。我们首先判断该数字是否有原根,如果有暴力枚举最小原根 g,根据原根判定定理看其是否合法。如果是,用原根个数定理中的条件去找出剩下的 gk 这些原根即可。

例题:【模板】原根,代码如下:

#include <bits/stdc++.h>
#define il inline
#define int long long

using namespace std;

const int Maxn = 1e6 + 5;
const int Inf = 2e9;

int T;
int n, d;

int prim[Maxn], tot, phi[Maxn];
int vis[Maxn];
int rt[Maxn];

void init(int N) {
	phi[1] = 1;
	for(int i = 2; i <= N; i++) {
		if(!vis[i]) {
			prim[++tot] = i;
			phi[i] = i - 1;
		}
		for(int j = 1, x; (x = prim[j] * i) <= N; j++) {
			vis[x] = 1;
			if(i % prim[j] == 0) {
				phi[x] = phi[i] * prim[j];
				break;
			}
			phi[x] = phi[i] * (prim[j] - 1);
		}
	}
	rt[2] = rt[4] = 1;
	for(int i = 2; i <= tot; i++) {
		for(int j = prim[i]; j <= N; j *= prim[i]) rt[j] = 1;
		for(int j = 2 * prim[i]; j <= N; j *= prim[i]) rt[j] = 1;
	}
}

int fac[Maxn], cnt;
void divd(int x) {
	cnt = 0;
	for(int i = 1; prim[i] <= x / prim[i]; i++) {
		if(x % prim[i] == 0) {
			fac[++cnt] = prim[i];
			while(x % prim[i] == 0) x /= prim[i];
		}
	}
	if(x > 1) fac[++cnt] = x;
}

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

int check(int g, int m) {//判断是否是原根
	if(qpow(g, phi[m], m) != 1) return 0;
	for(int i = 1; i <= cnt; i++) {
		if(qpow(g, phi[m] / fac[i], m) == 1) return 0;
	}
	return 1;
}

int findrt(int m) {//找最小原根
	for(int i = 1; i < m; i++) {
		if(check(i, m)) return i;
	}
}

int ans[Maxn], ret;

void getrt(int g, int m) {//找出所有原根
	int res = 1;
	ret = 0;
	for(int i = 1; i <= phi[m]; i++) {
		res = res * g % m;
		if(__gcd(phi[m], i) == 1) {
			ans[++ret] = res;
		}
	}
}

void solve() {
	cin >> n >> d;
	if(rt[n]) {//判断是否有原根
		divd(phi[n]);//分解质因数
		getrt(findrt(n), n);//找出原根
		sort(ans + 1, ans + ret + 1);
		cout << ret << '\n';
		for(int i = d; i <= ret; i += d) {
			cout << ans[i] << " ";
		}
		cout << '\n';
	}
	else {
		cout << "0\n\n";
	}
}

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> T;
	init(1e6);
	while(T--) solve();
	return 0;
}

3 指标

3.1 定义

指标,也被称作离散对数,实际上就是模意义下的对数运算。设 mN+ 且有原根 g,对于满足 gcd(a,m)=1 的整数 a,必存在唯一的 0k<φ(m),使得

gka(modm)

k 为以 g 为底模 m 的离散对数,或者指标,记作 k=ind(a)k=γ(a)

指标的求法很简单,既然是离散对数,那么直接用 BSGS 算法即可。

3.2 性质

指标的性质与普通对数类似,下面列举几条。注意下式中 a,b 均满足 a,bZ,gcd(a,m)=gcd(b,m)=1

性质 1:

ab(modm),则 γ(a)γ(b)(modφ(m))

该性质可以直接由阶的性质 2 中的推论得到。

性质 2:

γ(ab)γ(a)+γ(b)(modφ(m))

证明:

gγ(ab)abgγ(a)×gγ(b)gγ(a)+γ(b)(modm)。再由性质 1 可得 γ(ab)γ(a)+γ(b)(modφ(m))

性质 3:

γ(an)nγ(a)(modφ(m))

证明:对 γ(an)n1 次性质 2 即可。

4 例题

例 1 [BZOJ1420] Discrete Root

题意: 给定 k,a,p,求方程 xka(modp) 的所有在 [0,p1] 内解,保证 p 为质数且 a<p

既然 p 为质数,其一定存在原根 g。对方程做指标性质 1 可得 γ(xk)γ(a)(modφ(p))。再由指标性质 3 可得 kγ(x)γ(a)(modp1)。注意到此时方程化为了一个朴素同余方程的形式,用 exgcd 求出 γ(x) 的所有解并代入求出对应 x 即可。

例 2 [BZOJ2219] 数论之神

题意:给定 A,B,K,求方程 xAB(mod2K+1) 的所有在 [0,2K] 内解。

上面一道题其实只是为了引出这道题的。发现此时模数变为 2K+1,没有保证是质数,所以不一定有原根,难以直接求解。

不过我们可以对 2K+1 做质因数分解,设 P=2K+1=piαi,那么原来的方程可以化为若干线性同余方程 xAB(modpiαi)。由于 2K+1 必为奇数,所以 pi 一定是奇质数,所以 piαi 必存在原根。

我们对于每一个方程可以求出一个 xi,然后我们会发现只要最后的 x 对于所有方程满足 xxi(modpiαi),那么这个 x 就是一个合法答案。不难发现这是一个线性同余方程组,根据中国剩余定理,可以知道满足条件的 x[0,P1] 范围内只有一个。因此我们对每个方程求出它们解的个数再相乘就是最后答案。

那么现在的问题就是求 xAB(modpiαi) 的解的个数。由于此时不一定有 gcd(B,piαi)=1,所以不能直接像上一道题一样用指标求解。所以分类讨论:

  • gcd(B,piαi)=piαi 时:

    此时 piαiB,所以方程化为 xA0(modpiαi)。设 x=apit(gcd(a,pi)=1),代入有 aApitA0(modpiαi)。于是有 tAαi,解得 tαiA。那么实际上只需要让 piαiAx 即可,所以 x 取值有 piαi/piαiA=piαiαiA 种。

  • gcd(B,piαi)=1 时:

    此时就与上一道题是一样的了,先求出指标 γ(B),如果 gcd(A,φ(piαi))γ(B),那么取值就有 gcd(A,φ(piαi)) 种。

  • gcd(B,piαi)=pik 时:

    B=bpik,那么会有 xAbpik(modpiαi)。显然此时如果有解,那么 xA 中也必然有 pik。于是根据同余方程的消去律,可以得到 xApikb(modpiαik),第一项其实也就是 (xpikA)A

    那么此时 gcd(b,piαik) 就等于 1 了,回到了情况 2。但是注意到此时求出来的 x 的取值范围是 [0,piαik+kA) 的,但是我们要求的范围是 x[0,piαi) 的,所以还需要给求出来的结果乘上 pikkA

posted @   UKE_Automation  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示