原根与离散对数

一、原根


原根的概念

原根是一种数学符号,设m是正整数,a是整数,若a模m的阶等于φ(m),则称a为模m的一个原根。(其中φ(m)表示m的欧拉函数)
定义1 :(a模n的阶乘),设 a a n n 是互素的整数, a 0 , n > 0 a\not=0,n>0 。使得 a x 1 ( m o d   n ) a^x\equiv1(mod\ n) 成立的最小的正整数 x x 被称为 a a n n 的阶,并记作 o r d n a = x ord_na = x

定义2 :(原根),设 a a n n 是互素的整数, n > 0 n>0 。如果 o r d n a = φ ( n ) ord_na=\varphi(n) ,则称 a a 是模 n n 的原根,并称 n n 有一个原根。

例如,设 m = 7 , φ ( 7 ) = 6 m = 7,\varphi(7)=6

1 1 1 ( m o d   7 ) , 2 3 1 ( m o d   7 ) , 3 6 1 ( m o d   7 ) , 4 3 1 ( m o d   7 ) , 5 6 1 ( m o d   7 ) , 6 2 1 ( m o d   7 ) 1^1\equiv1(mod \ 7),2^3\equiv1(mod \ 7),3^6\equiv1(mod \ 7),4^3\equiv1(mod \ 7),5^6\equiv1(mod \ 7),6^2\equiv1(mod \ 7)

所以 3 , 5 3,5 是模 7 7 的两个原根, 2 , 4 , 6 2,4,6 不是模 7 7 的原根。

如何判断一个数 g g 是不是 模 m下的原根呢?

先对 φ ( m ) \varphi(m) 质因子分解,即 φ ( m ) = ( p 1 a 1 ) ( p 2 a 2 ) . . ( p k a k ) \varphi(m)=(p_1^{a1})(p_2^{a2})…..(p_k^{ak}) 。若恒有 g φ ( m ) p i 1 ( m o d    m ) \displaystyle g^{\frac{\varphi(m)}{p_i}} \not =1(mod\ \ m) 成立,那么 g g 就是 m m 的原根。

在这里插入图片描述在这里插入图片描述
【例题1 】POJ1284 Primitive Roots (积性函数)

题意:
给一个奇素数 n ( 1 , n 1 ) n,(1,n-1) 内的数 i ( i 1 , i 2 , i 3 , . . . , i n 1 ) i,(i^1,i^2,i^3,...,i^{n-1}) 分别 m o d     n mod\ \ \ n ,正好是 1 2 3 n 1 (1,2,3,,,n-1) ,可以不按顺序,求满足这个式子的 i i 的个数
思路:
本质就是求原根的个数,而求原根数有一个公式 原根数=phi(phi(m))

又由于给的数m是奇素数,所以phi[m] = m - 1;

所以答案就是phi[m-1]

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define ll long long 
using namespace std;

const int N = 7e4;
int phi[N];
int m;
void get_phi(int n){
	for(int i = 2; i <= n; i++) phi[i] = i;
	for(int i = 2; i <= n; i++){
		if(phi[i] == i){
			for(int j = i; j <= n; j += i){
				phi[j] = phi[j] / i * (i - 1);
			}
		}
	}
}
int main(){
	get_phi(N-1);
	while(scanf("%d",&x\m) != EOF){
		printf("%d\n",phi[m-1]);
	}
	return 0;
}

【例题2】51Nod 1135 原根
题意

设m是正整数,a是整数,若a模m的阶等于φ(m),则称a为模m的一个原根。(其中φ(m)表示m的欧拉函数)
给出1个质数P,找出P最小的原根。

思路
求模素数 p p 的原根的方法:对 p 1 p-1 素因子分解,即 p 1 = ( p 1 a 1 ) ( p 2 a 2 ) . . ( p k a k ) p-1=(p_1^{a1})(p_2^{a2})…..(p_k^{ak}) 。若恒有 g p 1 p i 1 ( m o d    p ) g^{\frac{p-1}{p_i}} \not =1(mod\ \ p) 成立,那么 g g 就是 p p 的原根(对于合数而言,只需要把 p 1 p-1 换成 φ ( p ) \varphi(p) 即可)

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;

const int N = 1e5 + 7;
int prime[N],prime_tot = 0,tot = 0,p[N];
bool prime_tag[N];
int n;
//素数筛法
void get_prime() {
	for(int i = 2; i < N; i++) prime_tag[i] = true;
	for(int i = 2; i < N; i++) {
		for(ll j = 1ll * i * i; j < N; j += i) {
			prime_tag[j] = false;
		}
	}
	for(int i = 2; i < N; i++)
		if(prime_tag[i]) prime[prime_tot++] = i;
}
//快速幂
ll qpow(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;
}
//分解质因子
void divide(int n) {
	tot = 0;
	for(int i = 0; i < prime_tot; i++) {
		if(n % prime[i] == 0) {
			//printf("%d ",prime[i]);
			p[tot++] = prime[i];
			while(n % prime[i] == 0 && n > 1) {
				n /= prime[i];
			}
		}
		if(n == 1) break;
	}
}
//判断是不是原根
bool check(int x) {
	for(int i = 0; i < tot; i++){
		if(qpow(x,(n-1)/p[i],n) == 1) return false;
	}
	return true;
}
int main() {
	get_prime();
	scanf("%d",&n);
	divide(n - 1);
	for(int i = 2; i < n; i++) {
		if(check(i)) {
			printf("%d\n",i);
			break;
		}
	}
	return 0;
}

二、离散对数


离散对数的概念

如果模 m m 有一个原根 g g ,则 g 0 , g 1 , g 2 , . . . , g φ ( m ) 1 g^0,g^1,g^2,...,g^{\varphi(m)-1} 组成模 m m 的一个简化剩余系(1~m中和m互质的元素集合)。也就是说对于任一个整数 a , g c d ( a , m ) = 1 a,gcd(a,m)=1 ,都可以唯一地表示为
a g γ ( m o d   m ) , 0 γ φ ( m ) 1 a\equiv g^\gamma(mod \ m),0\leq\gamma\leq\varphi(m)-1

g g 是模 m m 的一个原根,对于任一整数 a , g c d ( a , m ) = 1 a,gcd(a,m) = 1 ,都有 a g γ ( m o d   m ) , 0 γ φ ( m ) 1 a\equiv g^\gamma(mod \ m),0\leq\gamma\leq\varphi(m)-1 ,我们把 γ \gamma 称为以 g g 为底的 a a 对模 m m 的离散对数,记为 i n d g a ind_ga 。离散对数也称为指标。

之所以称为离散对数,是因为它定义在离散的整数集合上,而不是象普通对数那样定义在连续的实数集合上。

例如,已知模 18 18 的一个原根是 5 5 ,以 5 5 为底模 18 18 的离散对数。

1 5 0 ( m o d   18 ) , 5 5 1 ( m o d   18 ) , 7 5 2 ( m o d   18 ) , 11 5 5 ( m o d   18 ) , 13 5 4 ( m o d   18 ) , 17 5 3 ( m o d   18 ) 1\equiv5^0(mod \ 18),5\equiv5^1(mod \ 18),7\equiv5^2(mod \ 18),11\equiv5^5(mod \ 18),13\equiv5^4(mod \ 18),17\equiv5^3(mod \ 18)

在这里插入图片描述

对于实数对数,我们通常 两边同时取log,这样就可以将幂次变成多项式,在离散对数中,做了这样的变换后,模m则变成了模φ(m)。于是我们就可以将一些乘法操作变成加法操作,来简化或者解决一些运算问题.

一些重要性质

a b ( m o d   m ) i n d g a = i n d g b ( m o d    φ ( m ) ) a\equiv b(mod\ m) \Longleftrightarrow ind_ga=ind_gb(mod\ \ \varphi(m))
在这里插入图片描述

发布了141 篇原创文章 · 获赞 71 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/sinat_40872274/article/details/101116938