题意:给出一个奇素数,求出他的原根的个数,多组数据。
首先何为原根:设
m" role="presentation" style="position: relative;">m是正整数,
a" role="presentation" style="position: relative;">a是整数,若
m" role="presentation" style="position: relative;">m模
m" role="presentation" style="position: relative;">m的阶等于
ϕ(m)" role="presentation" style="position: relative;">ϕ(m),则称
a" role="presentation" style="position: relative;">a为模
m" role="presentation" style="position: relative;">m的一个原根(其中
ϕ(m)" role="presentation" style="position: relative;">ϕ(m)表示
m" role="presentation" style="position: relative;">m的欧拉函数)。
假设一个数
g" role="presentation" style="position: relative;">g对于
p" role="presentation" style="position: relative;">p来说是原根,那么
gi mod p" role="presentation" style="position: relative;">gi mod p的结果两两不同,且有
1<g<p,0<i<p" role="presentation" style="position: relative;">1<g<p,0<i<p可以称为是
p" role="presentation" style="position: relative;">p的一个原根。
可以表示为
gi mod p≠gj mod p" role="presentation" style="position: relative;">gi mod p≠gj mod p (
p" role="presentation" style="position: relative;">p为素数),并且
i≠j" role="presentation" style="position: relative;">i≠j且
0<i,j<p" role="presentation" style="position: relative;">0<i,j<p为
p" role="presentation" style="position: relative;">p的原根。
解决这个问题我们要使用以下定理:
如果
p" role="presentation" style="position: relative;">p有原根,则它恰有
ϕ(ϕ(p))" role="presentation" style="position: relative;">ϕ(ϕ(p))个不同的原根(无论
p" role="presentation" style="position: relative;">p是否为素数都适用)
因为题目给出的是一个奇素数,又因为对于一个素数
p" role="presentation" style="position: relative;">p,
ϕ(p)=p−1" role="presentation" style="position: relative;">ϕ(p)=p−1,所以我们最终要求的就是
ϕ(p−1)" role="presentation" style="position: relative;">ϕ(p−1)。
我们可以线性的筛出欧拉函数,具体操作与线性筛素数类似。
以下的三个性质是线性筛欧拉的关键,以下所有的p均为素数。
1.
ϕ(p)=p−1" role="presentation" style="position: relative;">ϕ(p)=p−1
2.若
i mod p=0,则ϕ(i∗p)=ϕ(i)∗p" role="presentation" style="position: relative;"> i mod p=0,则ϕ(i∗p)=ϕ(i)∗p
3.若
i mod p≠0,那么ϕ(i∗p)=ϕ(i)∗(p−1)" role="presentation" style="position: relative;"> i mod p≠0,那么ϕ(i∗p)=ϕ(i)∗(p−1)
最后粘上代码
#include
#include
#include
#include
using namespace std;
long long phi[1000000],num,prime[1000000],n;
bool pri[1000000];
void get_phi(int n)
{
memset(pri,true,sizeof(pri));
memset(phi,0,sizeof(phi));
phi[1]=1;
pri[1]=false;
for(int i=2;i<=n;++i)
{
if(pri[i])
{
prime[++num]=i;
phi[i]=i-1;
}
for(int j=1;j<=num,prime[j]*i<=n;++j)
{
pri[i*prime[j]]=false;
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
}
int main()
{
get_phi(100005);
while(cin>>n)
cout<1]<return 0;
}