SPOJ PROOT - Primitive Root
题目链接:http://www.spoj.com/problems/PROOT/
题目大意:给出一个整数p,p为素数,给出n个数x,判断x是否为p的原根。
解题思路:参考:http://www.apfloat.org/prim.html
大致思想:如果x是模p的原根,那么 ep(x) = p - 1, 否则 ep(x) 整除 p - 1。 而如果从1到p-1判断x的幂是否为1显然太耗费时间,实际上是只需要判断对于每个 p - 1的质因子 f 来说,是否有 x (p - 1) / f ≡ 1 (mod p) 即可。
代码:
1 const int maxn = 1e5 + 5; 2 ll p; 3 int n; 4 VI factors, primes; 5 bool vis[maxn]; 6 7 void dowork(){ 8 for(int i = 2; i < maxn; i++){ 9 if(!vis[i]) 10 for(int j = i * 2; j > 0 && j < maxn; j += i) 11 vis[j] = 1; 12 } 13 for(int i = 2; i < maxn; i++) 14 if(!vis[i]) primes.push_back(i); 15 } 16 void getf(){ 17 factors.clear(); 18 int x = p - 1; 19 for(int i = 0; i < primes.size(); i++){ 20 int u = primes[i]; 21 if(x % u == 0) factors.push_back(u); 22 while(x % u == 0) x /= u; 23 } 24 } 25 ll pow_mod(ll a, ll b, ll m){ 26 ll ans = 1, base = a % m; 27 while(b){ 28 if(b & 1) ans = ans * base % m; 29 base = base * base % m; 30 b >>= 1; 31 } 32 return ans % m; 33 } 34 bool check(int x){ 35 for(int i = 0; i < factors.size(); i++){ 36 int u = (p - 1) / factors[i]; 37 int tmp = pow_mod(x, u, p); 38 if(tmp == 1) return false; 39 } 40 return true; 41 } 42 int main(){ 43 dowork(); 44 while(scanf("%lld %d", &p, &n) && p){ 45 getf(); 46 for(int i = 1; i <= n; i++){ 47 int x; 48 scanf("%d", &x); 49 if(check(x)) puts("YES"); 50 else puts("NO"); 51 } 52 } 53 }
题目:
PROOT - Primitive Root
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 number p 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 ) separated 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.
Example
Input: 5 2 3 4 7 2 3 4 0 0 Output: YES NO YES NO
Explanation
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.