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 }
时间: 2024-11-05 06:10:10

SPOJ Prime or Not - 快速乘 - 快速幂的相关文章

hdu 5690 2016&quot;百度之星&quot; - 初赛(Astar Round2A) All X 快速二次幂 || 寻找周期

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5690 题意:m个数字全为x mod k ?= c;其中m <= 1010,0 < c,k <= 10,000; 法1:xxx = (10m-1)/9*x;但是n太大,需要同时mod.去除分母将式子变为:10m*x%(9k) - x%(9k) =? 9c ;其中 10m 快速二次幂即可: 时间复杂度为O(logn) 法2: 由于m个x数的产生对于mod具有可拆分性,所以直接求解周期即可: #i

Percona Server 5.6 RPM 快速安装&快速完全卸载

1.先快速安装,然后进行学习,参数文件慢慢再来学习. 安装包下载到/tmp路径下 # tar -xvf Percona-Server-5.6.34-79.1-r1c589f9-el6-x86_64-bundle.tar # ls *.rpm # rpm -ivh Percona-Server-shared-56-5.6.34-rel79.1.el6.x86_64.rpm # rpm -ivh Percona-Server-client-56-5.6.34-rel79.1.el6.x86_64.r

快速乘法,幂计算 hdu5666

在实际应用中为了防止数据爆出,在计算a*b%m和x^n%m时,可以采用此方法.在数论中有以下结论: a*b%m=((a%m)*(b*m))%m ; (a+b)%m=(a%m+b%m)%m ; _int64 Plus(_int64 a, _int64 b,_int64 m) { //计算a*b%m _int64 res = 0; while (b > 0) { if (b & 1) res=(res+a)%m; a = (a << 1) % m; b >>= 1; }

快速乘法/快速幂 算法

快速幂算法可以说是ACM一类竞赛中必不可少,并且也是非常基础的一类算法,鉴于我一直学的比较零散,所以今天用这个帖子总结一下 快速乘法通常有两类应用:一.整数的运算,计算(a*b) mod c  二.矩阵快速乘法 一.整数运算:(快速乘法.快速幂) 先说明一下基本的数学常识: (a*b) mod c == ( (a mod c) * (b mod c) ) mod c //这最后一个mod c 是为了保证结果不超过c 对于2进制,2n可用1后接n个0来表示.对于8进制,可用公式 i+3*j ==

快速模取幂

数论计算中经常出现的一种运算就是求一个数的幂ab对另外一个数n个模的运算,即计算: ab mod n (a,b,n是正整数) 由于计算机只能表示有限位的整数,所以编程时模取幂的运算要注意值的大小范围,当ab的值超过整数范围时,mod运算便无法进行. 如何解决这个问题,我们引出一个能计算ab mod n的值的有用算法--反复平方法,首先我们必须明确: d=ab mod n=(-((((a mod n)*a)mod n)*a)mod n-*a)mod n    {共b个a} 由此可以引出一个迭代式

常用快速读入快速输出

此文为博主原创,转载时请通知博主,并把原文链接放在正文醒目位置. 简要介绍 众所周知,就运行速度而言,getchar()快于scanf快于cin,putchar()快于printf快于cout. 但getchar()和putchar()每次只能操作一个字符,使用起来比较麻烦. 于是就出现了快读.快速输出. 它们的原理都是把需要读入\输出的数字(本文只能用于处理整数)一位一位地输出,从而减少运行时间. 代码 1 #include<cstdio> 2 using namespace std; 3

2179: FFT快速傅立叶|快速傅里叶变换

背板子大法吼 #include<algorithm> #include<iostream> #include<complex> #include<cstdlib> #include<cstring> #include<cstdio> #include<vector> #include<queue> #include<ctime> #include<cmath> #include<m

BZOJ 2179 FFT快速傅立叶 快速傅里叶变换

题目大意:给定两个高精度整数,求两个数的乘积 FFT大法好 系统的complex比手写慢了2.5倍 简直吓死人- - #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 131080 #define PI 3.1415926535897932384626433832795028841971

快速乘、快速幂(矩阵快速幂)

当mod一个大数p的时候,还有进行乘法的时候可能会爆long long的时候,就用快速乘或者快速幂. 参考:http://www.cnblogs.com/whywhy/p/5066730.html 先上模板: 快速乘: ll multi(ll a,ll b,ll m) { ll ans=0; while(b) { if(b&1) (ans+=a) %= m; (a=a*2) %= m; b/=2; } return ans; } 快速幂: ll pow_mod(ll a,ll b,ll m) {