SPOJ Prime or Not - 快速乘 - 快速幂
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPOJ Prime or Not - 快速乘 - 快速幂相关的知识,希望对你有一定的参考价值。
Given the number, you are to answer the question: "Is it prime?"
Solutions to this problem can be submitted in C, C++, Pascal, Perl, Python, Ruby, Lisp, Hask, Ocaml, Prolog, Whitespace, Brainf**k and Intercal only.
Input
t – the number of test cases, then t test cases follows. [t <= 500]
Each line contains one integer: N [2 <= N <= 2^63-1]
Output
For each test case output string "YES" if given number is prime and "NO" otherwise.
Example
Input: 5 2 3 4 5 6 Output: YES YES NO YES NO
题目大意是说,给你一个能够用有符号64位整型存储的数,判断它是否是素数。
用费马小定理,多次随机生成一个底数a,然后n - 1次幂,判断模n意义下是否是1。
为了充分表示对rand()的嫌弃,于是手写了一个随机数生成器。详细请见[here]
Code
1 /** 2 * SPOJ 3 * Problem#PON 4 * Accepted 5 * Time:180ms 6 * Memory:15360k 7 */ 8 #include<iostream> 9 #include<cstdio> 10 #include<cctype> 11 #include<cmath> 12 #include<ctime> 13 #include<cstring> 14 #include<cstdlib> 15 #include<fstream> 16 #include<sstream> 17 #include<algorithm> 18 #include<map> 19 #include<set> 20 #include<queue> 21 #include<vector> 22 #include<stack> 23 using namespace std; 24 typedef bool boolean; 25 #define INF 0xfffffff 26 #define smin(a, b) a = min(a, b) 27 #define smax(a, b) a = max(a, b) 28 template<typename T> 29 inline boolean readInteger(T& u){ 30 char x; 31 int aFlag = 1; 32 while(!isdigit((x = getchar())) && x != ‘-‘ && x != -1); 33 if(x == -1) { 34 ungetc(x, stdin); 35 return false; 36 } 37 if(x == ‘-‘){ 38 x = getchar(); 39 aFlag = -1; 40 } 41 for(u = x - ‘0‘; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - ‘0‘); 42 ungetc(x, stdin); 43 u *= aFlag; 44 return true; 45 } 46 47 #define LL long long 48 49 typedef class Random { 50 public: 51 unsigned int pre; 52 unsigned int seed; 53 54 Random():pre(0), seed((unsigned) time (NULL)) { } 55 Random(int seed):pre(0), seed(seed) { } 56 57 /** 58 * Generate a random number. 59 * @return this function will return the random number it gernerated 60 */ 61 unsigned int rand() { 62 // unsigned int ret = (seed * 7361238 + seed % 20037 * 1244 + pre * 12342 + 378211) * (seed + 134543); 63 // unsigned int ret = (seed * 7361238 + seed % 20037 * 1244 + pre * 12342 + 378211 + time(NULL) * pre) * (seed + 134543); 64 unsigned int ret; 65 if(ret & 1) 66 ret = (seed * 7361238 + seed % 20037 * 1245 + pre * 456451 + (time(NULL) * (pre * 5 + seed * 3 + 37)) + 156464); 67 else 68 ret = (seed * 7361238 + seed % 20037 * 1241 + pre * 456454 + (time(NULL) * (pre * 7 + seed * 3 + 18)) + 156464); 69 pre = seed; 70 seed = ret; 71 return ret; 72 } 73 }Random; 74 75 inline void setLLhighBit(long long& x, int a) { 76 int* p = (int*)&x; 77 *(p + 1) = a; 78 } 79 80 inline void setLLlowBit(long long& x, int a) { 81 int* p = (int*)&x; 82 *p = a; 83 } 84 85 inline void cleanLLSignFlag(long long& a) { 86 a &= (1ull << 63) - 1; 87 } 88 89 template<typename T> 90 T mul_mod(T a, T b, T& moder) { 91 if(b == 1) return a; 92 T temp = mul_mod(a, b >> 1, moder); 93 if(b & 1) return (((temp + temp) % moder) + a) % moder; 94 return (temp + temp) % moder; 95 } 96 97 template<typename T> 98 T pow_mod(T a, T pos, T& moder) { 99 if(pos == 1) return a; 100 T temp = pow_mod(a, pos >> 1, moder); 101 if(pos & 1) return mul_mod(mul_mod(temp, temp, moder), a, moder); 102 return mul_mod(temp, temp, moder); 103 } 104 105 int T; 106 LL n; 107 Random r; 108 109 inline void work() { 110 readInteger(n); 111 if((n & 1) == 0) { 112 if(n == 2) puts("YES"); 113 else puts("NO"); 114 return; 115 } 116 unsigned int l, h; 117 LL a, r1; 118 for(int t = 0; t < 20; t++) { 119 l = r.rand(); 120 h = r.rand(); 121 setLLhighBit(a, h); 122 setLLlowBit(a, l); 123 cleanLLSignFlag(a); 124 a = (a % (n - 2)) + 2; 125 r1 = pow_mod(a, n - 1, n); 126 if(r1 != 1) { 127 puts("NO"); 128 return; 129 } 130 } 131 puts("YES"); 132 } 133 134 int main() { 135 readInteger(T); 136 while(T--) { 137 work(); 138 } 139 return 0; 140 }
以上是关于SPOJ Prime or Not - 快速乘 - 快速幂的主要内容,如果未能解决你的问题,请参考以下文章