设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 }