原根(2)



对于两个正整数gcd(a,m)=1,由欧拉定理可知,存在正整数 d ≤ m-1, 比如说欧拉函数 d=φ(m),即小于等于 m的正整数中与 m互素的正整数的个数,使得 ad≡1(mod m)
由此,在gcd(a,m)=1时,定义 a对模m的指数 δm(a)为使 ad≡1(mod m) 成立的最小的正整数 d。由前知 δm(a) 一定小于等于 φ (m),若δm(a) = φ(m),则称a是模 m的原根。

另一种定义
假设一个数g对于P来说是原根,那么gi mod P的结果两两不同,且有 1 < g < P, 1 < i < P,那么g可以称为是P的一个原根
简单来说,gi mod p ≠ gj mod p (p为素数),其中i≠j且i, j介于1至(p-1)之间,则g为p的原根。

简单的来说,如果g是P的原根,那么g的(1…P-1)次幂mod P的结果一定互不相同

例如:
设m= 7,则φ(7)等于6。φ(7)表示7的欧拉函数。
设a= 2,由于23=8≡1(mod 7),而3<6,所以 2 不是模 7 的一个原根。
设a= 3,由于31≡3(mod 7),32≡2(mod 7),33≡6(mod 7),34≡4(mod 7),35≡5(mod 7),36≡1(mod 7),所以 3 是模 7 的一个原根。

如何求解:

一、枚举

从2开始枚举,然后暴力判断g(P-1) ≡ 1 (mod P)是否当且当指数为P-1的时候成立
而由于原根一般都不大,所以可以暴力得到.
二、讲究方法
例如求任何一个质数x的任何一个原根,一般就是枚举2到x-1,并检验。有一个方便的方法就是,求出x-1所有不同的质因子p1,p2…pm,对于任何2<=a<=x-1,判定a是否为x的原根,只需要检验a((x-1)/p1),a((x-1)/p2),…a((x-1)/pm)这m个数中,是否存在一个数mod x为1,若存在,a不是x的原根,否则就是x的原根。
原来的复杂度是O(P-1),现在变成O(m)*log(P-1)m为x-1质因子的个数。很明显质因子的个数远远小于x-1。
证明可用欧拉定理和裴蜀定理:

裴蜀定理
说明了对任何整数a、b和它们的最大公约数d,关于未知数x和y的线性丢番图方程(称为裴蜀等式):
ax + by = m
有解当且仅当m是d的倍数。裴蜀等式有解时必然有无穷多个整数解,每组解x、y都称为裴蜀数,可用辗转相除法求得。
例如,12和42的最大公因子是6,则方程12x + 42y = 6有解。事实上有(-3)×12 + 1×42 = 6及4×12 + (-1)×42 = 6。
特别来说,方程 ax + by = 1 有解当且仅当整数a和b互素。
裴蜀等式也可以用来给最大公约数定义:d其实就是最小的可以写成ax + by形式的正整数。这个定义的本质是整环中“理想”的概念。因此对于多项式整环也有相应的裴蜀定理。

证明
假设存在一个t < phi(x)=x-1使得at ≡ 1 (mod x)
那么由裴蜀定理,一定存在一组k,r使得kt=(x-1)r+gcd(t,x-1)
而由欧拉定理有,a(x-1) ≡ 1 (mod x)
于是1 ≡ a(kt) ≡ a(xr-r+gcd(t,x-1)) ≡ agcd(t,x-1) (mod x)
而t < x-1故gcd(t,x-1) < x-1
又gcd(t,x-1)|x-1 于是gcd(t,x-1)必整除(x-1)/p1,(x-1)/p2…(x-1)/pm其中至少一个,设其一为(x-1)/pi
那么a((x-1)/pi) ≡ (agcd(t,x-1))s ≡ 1s ≡ 1 (mod x)
这与假设矛盾

模板


vector<ll> a;

ll pow_mod(ll a, ll i, ll n){
    if (i == 0){
        return 1%n;
    }
    int tmp = pow_mod(a, i>>1, n);
    tmp = tmp * tmp % n;
    if (i&1){
        tmp = tmp * a % n;
    }
    return tmp;
}

bool g_test(ll g, ll p) {
    for (ll i = 0; i < a.size(); i++){
        if (pow_mod(g, (p-1)/a[i], p) == 1){
            return 0;
        }
    }
    return 1;
}

ll primitive_root(ll p){
    a.clear() ;
    ll tmp = p-1;
    for (ll i = 2; i <= tmp; i++) {
        if (tmp%i == 0){
            a.push_back(i);
            while(tmp%i == 0){
                tmp /= i;
            }
        }
    }
    if (tmp != 1){
        a.push_back(tmp);
    }
    ll g = 1;
    while(true){
        if (g_test(g, p)){
            return g;
        }
        g++;
    }
}
  
  
  • 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

关于原根个数问题
以下内容来自知乎
对于正整数 gcd(a,m)=1,如果a是模m的原根,那么a是整数模m乘法群的一个生成元,由于又φ(m)个元素,而它的生成元就是他的可逆元的数目即φ(φ(m))。

“生成元的个数等于可逆元的数目”指的是 Z/ϕ(m)Z 这个群中可逆元的个数。

因为a 是 (Z/mZ)^{×}的生成元。 所以 (Z/mZ)^{×}同构于循环群(Z/ϕ(m)Z,+)。 而(Z/mZ)^{×}的原根对应过来就是Z/ϕ(m)Z的生成元。 而Z/ϕ(m)Z的生成元就是Z/ϕ(m)Z中×的可逆元。 所以一共是ϕ(ϕ(m))个。

——————分割线————————
poj-1284 Primitive Roots

#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#define N 1010
using namespace std;

const int Max = 65540;

int minDiv[Max], phi[Max], sum[Max];

void getPhi() {
    for (int i = 1; i < Max; i++) {
        minDiv[i] = i;
    }
    for (int i = 2; i*i < Max; i++){
        if (minDiv[i] == i){
            for (int j = i*i; j < Max; j += i){
                minDiv[j] = i;
            }
        }
    }
    phi[1] = 1;
    for (int i = 2; i < Max; i++) {
        phi[i] = phi[i / minDiv[i]];
        if ((i / minDiv[i]) % minDiv[i] == 0){
            phi[i] *= minDiv[i];
        } else {
            phi[i] *= minDiv[i] - 1;
        }
    }
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("1.txt", "r", stdin);
#endif
    ios::sync_with_stdio(false);
    cin.tie(0);
    getPhi();
    int p;
    while(cin >> p){
        cout << phi[p-1] << endl;
    }
    return 0;
}

  
  
  • 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


转载自:https://blog.csdn.net/qq_21120027/article/details/52832543



对于两个正整数gcd(a,m)=1,由欧拉定理可知,存在正整数 d ≤ m-1, 比如说欧拉函数 d=φ(m),即小于等于 m的正整数中与 m互素的正整数的个数,使得 ad≡1(mod m)
由此,在gcd(a,m)=1时,定义 a对模m的指数 δm(a)为使 ad≡1(mod m) 成立的最小的正整数 d。由前知 δm(a) 一定小于等于 φ (m),若δm(a) = φ(m),则称a是模 m的原根。

猜你喜欢

转载自blog.csdn.net/dt_kang/article/details/79938074