SPOJ Primitive Root :判断一个数模p的阶是否是p-1

Description


In the field of Cryptography, prime numbers play an important role. We are interested in a scheme called "Diffie

-Hellman" key exchange which allows two communicating parties to exchange a secret key. This method requires

 a prime numberp and r which is a primitive root of p to be publicly known. For a prime number p, r is a primitive 

root if and only if it's exponents r, r2, r3, ... , rp-1 are distinct (mod p). Cryptography Experts Group (CEG) is trying

to develop such a system. They want to have a list of prime numbers and their primitive roots. You are going to

write a program to help them. Given a prime number p and another integer r < p , you need to tell whether r is a

primitive root of p.


Input

There will be multiple test cases. Each test case starts with two integers p ( p < 2 31 ) and n (1 ≤ n ≤ 100 ) sepa

rated by a space on a single line. p is the prime number we want to use and n is the number of candidates we 

need to check. Then n lines follow each containing a single integer to check. An empty line follows each test 

case and the end of test cases is indicated by p=0 and n=0 and it should not be processed. The number of test

 cases is atmost 60.

Output

For each test case print "YES" (quotes for clarity) if r is a primitive root of p and "NO" (again quotes for clarity) otherwise.


Sample Input

Input:
5 2
3
4

7 2
3
4

0 0


Output:
YES
NO
YES
NO

In the first test case 31, 32 , 33 and 34 are respectively 3, 4, 2 and 1 (mod 5). So, 3 is a primitive root of 5.

41, 42 , 43 and 44 are respectively 4, 1, 4 and 1 respectively. So, 4 is not a primitive root of 5.


//题意:给出p和n。之后个出n个数,判断这些数模p的阶是否是p-1;
//《数论概论》中“幂模p与原根”一章中有提到阶的概念: 如果a不被素数p整除,则a模p的阶是指使得
a^e=1(mod p)的最小指数e>=1; 例如2、3、4、5、6模7的阶分别是3、6、3、6、2。 并且本章中
给出一些重要的性质,其中有: 一个数a模p的阶e总能整除p-1。  所以可以枚举p-1的因子factor 
(不包括p-1),如果存在小于p-1的因子满足a^factor=1(mod p) 则说明a模p的阶不是p-1;
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<algorithm>
#include<ctime>
using namespace std;
#define maxn 65560
#define LL __int64

int factor[maxn];
LL mod_exp(LL a,LL r,LL p)
{
	LL d=1;
	a%=p;
	while(r)
	{
		if(r&1) d=d*a%p;
		a=a*a%p;
		r>>=1;
	}
	return d%p;
}

int main()
{
	int p,n,x;
	while(~scanf("%d%d",&p,&n),p|n)
	{
		int cnt=0,i;
		for(i=2;i<=(int)sqrt(1.0*(p-1));i++)
			if((p-1)%i==0)
				factor[++cnt]=i,factor[++cnt]=(p-1)/i;
		while(n--)
		{	
			bool flag=true;
			scanf("%d",&x);
			for(i=1;i<=cnt;i++)
				if(mod_exp(x,factor[i],p)==1) //存在比p-1小的指数满足a^factor=1(mod p)
				{
					flag=false;
					break;
				}
			printf("%s\n",flag?"YES":"NO");
		}
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值