设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
Code :
/*
设 m 是正整数,a是整数,若a模m的阶等于φ(m),则称 a 为 模m的一个原根。(其中φ(m)表示m的欧拉函数)
阶:gcd(a,m)=1,使得 a^r%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就为原根。
欧拉函数 Euler函数表达通式:euler(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…(1-1/pn),
其中p1,p2……pn为x的所有素因数,x是不为0的整数。euler(1)=1(唯一和1互质的数就是1本身)。
***素数m的欧拉函数 φ(m)=m-1
(a,m)=1; m>=1
a^x % m=1 且 x = φ(m) --m的欧拉函数
a^ φ(m) %m=1 -> a为模m的一个原根
*/
#include<iostream>
#include<vector>
using namespace std;
typedef long long LL;
int n;
LL ans;
vector<int> ive;
void get_Prime(int x);
LL get_pow(LL a,LL b,int mod);
int main()
{
ios::sync_with_stdio(false);
cin>>n;
get_Prime(n-1);
for(int i=2;i<n;++i)
{
bool boo=true;
for(auto t:ive)
if(get_pow(i,(n-1)/t,n)==1){
boo=false; break;
}
if(boo==true){
ans=i; break;
}
}
cout<<ans<<endl;
return 0;
}
void get_Prime(int x)//线性筛选素数 NUM 素数个数
{
for(int i=2; i*i<=x; i++)
if(x%i==0){
ive.push_back(i);
while(x%i==0){
x/=i;
}
}
if(x>1) ive.push_back(x);
}
LL get_pow(LL a,LL b,int mod)//快速幂取余
{
LL res=1;
while(b>0){
if(b&1) res=res*a%mod;
b=b>>1;
a=a*a%mod;
}
return res;
}