spoj PROOT

题目链接: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;
}


你可能感兴趣的:(spoj PROOT)