病了一个多星期了,这两天看了下原根的定义,和一些基本题型,与之经常有关联的还有阶。
阶是设m>1,gcd(a,m)=1,使得成立的最小的r,称为a对模m的阶。
性质:
如果一个数有原根,那么它一共有φ(φ(m))个原根。如果p为素数,那么素数p一定存在原根,并且模p的原根的个数为φ(p−1)个。
定理:若,
,
,则
。
定理:设是正整数,
是整数,若
模
的阶等于
,则称
为模
的一个原根。
假设一个数对于模
来说是原根,那么
的结果两两不同,且有
,那么
可以称为是模
的一个原根,归根到底就是
当且仅当指数为
的时候成立。(这里
是素数)
模有原根的充要条件:
,其中
是奇素数。
求模素数原根的方法:对
素因子分解,即
是
的标准分解式,若恒有
成立,则就是
的原根。(对于合数求原根,只需把
换成
即可)
下面是求原根的代码:(直接暴力即可)
#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
int zys[50];
int p;
int o;
int n;
int ksm(int a,int c,int b)
{
long long re=1;
long long t=a;
while(c)
{
if(c&1)re=re%b*t%b;
t=t%b*t%b;
c>>=1;
}
return re;
}
int pd(int x)
{
for(int i=1;i<=o;i++)
{
if(ksm(x,(p-1)/zys[i],p)%p==1)return 0;
}
return 1;
}
int main()
{
scanf("%d",&p);
int pp=p;
p--;
for(int i=2;i<=sqrt(p);i++)
{
if(p==1)break;
if(p%i==0)
{
o++;
zys[o]=i;
while(p%i==0)
{
p/=i;
}
}
}
if(p!=1)
{
o++;
zys[o]=p;
}
p=pp;
for(int i=2;i<p;i++)
{
if(pd(i))
{
printf("%d",i);
break;
}
}
return 0;
}