整数的阶
定义1:如果n为正整数,且a为与n互素的整数。则根据,必然存在一个最小整数x,使得
,则该最小整数x称为a模n的阶,记为
。 如
。
定理1:若a与n互素,则正整数x是的解的必要条件为,
。
推论1:由于a与n互素,因此是
的一个解,因此
。
原根
定义2:如果r和n是互素的整数且n>0,那么当时称r为n的原根。
猜想1:只有当n为2、4、、
(p为奇素数)时,n才有原根。
以上就是原根的基本定义,以及一些基本的定理了。
对于素数p而言,一定存在原根。根据推论1以及
,因此对于某个整数g来说,枚举
除自身外的因子,如果存在一个因子x使得
成立,则说明
说明g不为p的原根。反之,若对于
除自身外的所有因子x满足
,则g为p的原根。
因为枚举因子可能会超时,所以考虑若的某个因子x满足
,那么
也一定满足,对
做唯一分解
,那么如果存在x(x < p - 1)使得
,则必然存在
是x的倍数,即存在
。因此我们枚举g(1<g<p),并判断是否存在
,就可以判断g是不是p的原根了。
例题:51nod1135
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll qpow(ll a,ll b,ll mod){//快速幂a^b%mod
ll res = 1;
a %= mod;
while(b){
if(b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
set<int> fac;//存n的素因子
void divide(int n){
int len = sqrt(n);
for(int i = 2;i <= len;++i)
if(n % i == 0){
while(n % i == 0) n /= i;
fac.insert(i);
}
if(n != 1) fac.insert(n);
}
bool check(int g,int P){
for(auto pi:fac)
if(qpow(g,(P - 1) / pi,P) == 1) return false;//存在g^x=1(mod p) x < phi(p)
return true;
}
int main(){
int P;
cin>>P;
divide(P - 1);
for(int g = 2;g < P;++g)
if(check(g,P)){
cout<<g<<endl;
break;
}
return 0;
}