51nod 1135 原根

题目链接:51nod 1135 原根

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

阶:gcd(a,m)=1,使得这里写图片描述成立的最小的 r,称为 a 对 模m 的 阶

φ(m):在[1,m)的区间内与m互质的数的个数。

求模素数p的原根a的方法:

因为p为素数,所以φ(p)=p-1, 这题就是要找最小的a使得 a^(p-1)%p = 1 成立(根据费马小定理,该式一定成立),

先求p-1所有不同的 质因子 p1,p2…pm,

对任何整数 a ∈[1,p-1], 检验 a 是否为 p 的原根,

检验方法:a^((p-1)/p1),a^((p-1)/p2),...a^((p-1)/pm) 中是否存在一个 模p 等于 1 ,

存在的话 a 就不是 模p 的一个原根(即p-1就不是a对模p的阶),否则a就为原根。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<queue>
 6 #define CLR(a,b) memset((a),(b),sizeof((a)))
 7 using namespace std;
 8 typedef long long ll;
 9 const int N = 50000;
10 int prime[N];//prime[0] 存的是素数的个数
11 int ppri[N];//p-1的质因子
12 void getPrime(){
13     CLR(prime , 0);
14     for(int i = 2;i < N; i++){
15         if(!prime[i])
16             prime[ ++prime[0] ] = i;
17         for(int j = 1; j <= prime[0] && prime[j] <= N / i; j++){
18             prime[ prime[j] * i ] = 1;
19             if(i % prime[j] == 0) break;
20         }
21     }
22 }
23 ll pow_m(ll a, ll n, ll m){
24     ll t = a % m;
25     ll r = 1;
26     while(n > 0){
27         if(n & 1)
28             r = r * t % m;
29         t = t * t % m;
30         n >>= 1;
31     }
32     return r;
33 }
34 int divide(int n){//分解合数n的质因子
35     int cnt = 0;
36     for(int i = 1; prime[i] * prime[i] <= n; ++i){
37         if(n % prime[i] == 0){
38             ppri[++cnt] = prime[i];
39             while(n % prime[i] == 0){
40                 n /= prime[i];
41             }
42         }
43     }
44     if(n > 1) ppri[++cnt] = n;
45     return cnt;
46 }
47 int main(){
48     int p, i, a, t, f;
49     getPrime();
50     scanf("%d", &p);
51     int cnt = divide(p - 1);//p-1 的 质因子个数
52     for(a = 2; a <= p - 1; ++a){//原根从 2 到 p-1 枚举
53         f = 1;
54         for(i = 1; i <= cnt; ++i){
55             t = (p - 1) / ppri[i];
56             if( pow_m(a, t, p) == 1){
57             //存在a^((p-1)/ppr[i]) mod p = 1, 则 a 不是质数p的原根
58                 f = 0; break;
59             }
60         }
61         if(f){
62             printf("%d
",a);
63             break;
64         }
65     }
66     return 0;
67 }
View Code
原文地址:https://www.cnblogs.com/GraceSkyer/p/5990485.html