设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
首先这道题放基础题里是很不满的!
顶上的博客最好要看一下哒,看了能对原根有更好的理解。
这里只介绍一下原根的定义,其他博客里都写得很清楚~
所谓原根,若a为m的原根。就是a^1,a^2,...,a^m-1 模m的值各不相同,那么a就是m的原根。
好了其他其实不用讲了qwq
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;
int P,cnt,n,num,prime[100000],ans[100000];
bool flag[100100];
long long power(long long a,long long m,long long mod){
if(!m) return 1;
a=a%mod;
long long res=1;
while(m){
if(m%2) res=res*a%mod;
a=a*a%mod;
m/=2;
}
return res;
}
void divide(int n){
num=0;
int t=(int)sqrt(1.0*n);
for(int i=1;prime[i]<=t;i++)
if(n%prime[i]==0){
ans[++num]=prime[i];
while(n%prime[i]==0) n/=prime[i];
}
if(n>1) ans[++num]=n;
}
bool check(int x){
for(int i=1;i<=num;i++)
if(power(x,(P-1)/ans[i],P)==1) return false;
return true;
}
int main()
{
scanf("%d",&P);
for(int i=2;i<=100000;i++){
if(!flag[i]) prime[++cnt]=i;
for(int j=1;j<=cnt;j++){
if(i*prime[j]>100000) break;
flag[i*prime[j]]=1;
if(i%prime[j]==0) break;
}
}
divide(P-1);
for(int i=2;i<=P;i++)
if(check(i)) {printf("%d\n",i);return 0;}
return 0;
}