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 - 快速乘 - 快速幂的主要内容,如果未能解决你的问题,请参考以下文章

Spoj PRIME1 - Prime Generator

spoj2 prime1 (区间筛)

SPOJ CZ_PROB1 - Summing to a Square Prime

运算符

Prime Independence

bzoj 2820 / SPOJ PGCD 莫比乌斯反演