51nod 1135 原根

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

给出1个质数P,找出P最小的原根。
Input
输入1个质数P(3 <= P <= 10^9)
Output
输出P最小的原根。
Input示例
3
Output示例
2

原根的性质看了好久才看懂。由于质数的欧拉函数就是p-1,所以这题就是求一个最小的a(a<p) 使的只有(a^(p-1))%p=1成立。


 1 #include <iostream>
 2 #include <string.h>
 3 #include <stdio.h>
 4 #include <math.h>
 5 #define ll long long
 6 using namespace std;
 7 const int MAX = 50000;
 8 int prime[MAX],ppri[MAX];
 9 void get_prime(){
10     for(int i = 2; i <= MAX; i ++){
11         if(!prime[i])prime[++prime[0]] = i;
12         for(int j = 1; j <= prime[0]&& prime[j] < MAX/i; j ++){
13             prime[prime[j]*i] = 1;
14             if(i%prime[j] == 0)break;
15         }
16     }
17 }
18 int get_num(int n){
19     int cnt = 0;
20     for(int i = 1; prime[i]*prime[i] <= n; i ++){
21         if(n%prime[i] == 0){
22             ppri[++cnt] = prime[i];
23             while(n%prime[i] == 0)n/=prime[i];
24         }
25     }
26     if(n>1)ppri[++cnt]=n;
27     return cnt;
28 }
29 ll mod_mul(ll a, ll b, ll n){
30     ll cnt = 0LL;
31     while(b){
32         if(b&1LL) cnt = (cnt+a)%n;
33         a=(a+a)%n;
34         b >>= 1LL;
35     }
36     return cnt;
37 }
38 ll mod_exp(ll a, ll b, ll n){
39     ll res = 1LL;
40     while(b){
41         if(b&1LL) res = mod_mul(res,a,n);
42         a = mod_mul(a,a,n);
43         b >>= 1LL;
44     }
45     return res;
46 }
47 int main(){
48     int n;
49     cin>>n;
50     get_prime();
51     int cnt = get_num(n-1);
52     for(int a = 1; ; a ++){
53         int flag1 = 1;
54         for(int i = 1; i <= cnt; i ++){
55             int t = (n-1)/ppri[i];
56             if(mod_exp(a,t,n)==1){
57                 flag1 = 0;break;
58             }
59         }
60         if(flag1)return 0*printf("%d
",a);
61     }
62     return 0;
63 }
原文地址:https://www.cnblogs.com/xingkongyihao/p/7202280.html