题目链接:http://www.spoj.com/problems/PROOT/
题目大意:多组数据,给你一个质数P(p<2^31),n个r,对于每个r,判断r是否是P的原根
题目分析:r为P的原根的充要条件是,对于P的每一个质因数p,r^((P-1)/p)模P不为1.
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=100100;
bool valid[maxn];
int prim[maxn],pr[maxn];
int primm=0,c; //c为n质因子的个数
void getPrime(int n,int &tot) //n为筛素数的范围,tot为素数总数,ans[]为prim数组
{
memset(valid,true,sizeof(valid));
for (int i=2;i<=n;i++)
{
if (valid[i])
{
tot++;
prim[tot]=i;
for (int j=2;j<=n/i;j++)
valid[i*j]=0;
}
}
}
void cal(LL n)
{
LL t=n,a;
c=0;
for (int i=1;prim[i]*prim[i]<=n,i<=primm;i++)
{
if (n%prim[i]==0)
{
c++;
pr[c]=prim[i];
while (n%prim[i]==0) n/=prim[i];
}
}
if (n>1)
{
c++;
pr[c]=n;
}
}
LL quick_mod(LL a,LL b,LL m)
{
LL ans=1;
a%=m;
while (b)
{
if (b&1)
{
ans=ans*a%m;
b--;
}
b>>=1;
a=a*a%m;
}
return ans;
}
int main()
{
LL P,t,n;
getPrime(maxn-1,primm);
cin>>P>>n;
while (n+P!=0)
{
cal(P-1);
for (int i=1;i<=n;i++)
{
LL x;
cin>>x;
bool flag=true;
for (int j=1;j<=c;j++)
{
t=(P-1)/pr[j];
if (quick_mod(x,t,P)==1)
{
flag=false;
break;
}
}
if (flag) printf("YES\n");
else printf("NO\n");
}
cin>>P>>n;
}
return 0;
}