POJ 1811Prime Test(米勒拉宾素数测试)

直接套用模板,以后接着用

这里还有一个素因子分解的模板

  1 #include <map>
  2 #include <set>
  3 #include <stack>
  4 #include <queue>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <vector>
  8 #include <cstdio>
  9 #include <cctype>
 10 #include <cstring>
 11 #include <cstdlib>
 12 #include <iostream>
 13 //#include <algorithm>
 14 using namespace std;
 15 #define INF 0x3f3f3f3f
 16 #define inf ((LL)1<<40)
 17 #define lson k<<1, L, mid
 18 #define rson k<<1|1, mid+1, R
 19 #define mem0(a) memset(a,0,sizeof(a))
 20 #define mem1(a) memset(a,-1,sizeof(a))
 21 #define mem(a, b) memset(a, b, sizeof(a))
 22 #define FOPENIN(IN) freopen(IN, "r", stdin)
 23 #define FOPENOUT(OUT) freopen(OUT, "w", stdout)
 24 template<class T> T ABS ( T a) { return a >= 0 ? a : -a;   }
 25 template<class T> T CMP_MIN ( T a, T b ) { return a < b;   }
 26 template<class T> T CMP_MAX ( T a, T b ) { return a > b;   }
 27 template<class T> T MAX ( T a, T b ) { return a > b ? a : b; }
 28 template<class T> T MIN ( T a, T b ) { return a < b ? a : b; }
 29 template<class T> T GCD ( T a, T b ) { return b ? GCD ( b, a % b ) : a; }
 30 template<class T> T LCM ( T a, T b ) { return a / GCD ( a, b ) * b;     }
 31 template<class T> void SWAP( T& a, T& b ) { T t = a; a = b;  b = t;     }
 32
 33 typedef __int64 LL;
 34 //typedef long long LL;
 35 const int MAXN = 10005;
 36 const int MAXM = 110000;
 37 const double eps = 1e-14;
 38 const double PI = 4.0 * atan(1.0);
 39
 40
 41
 42
 43 LL n, ans;
 44 int t;
 45
 46
 47
 48
 49 #define Times 10
 50
 51 //产生[0, n-1]的一个随机数
 52 LL random(LL n)
 53 {
 54     return ((double)rand() / RAND_MAX * n + 0.5);
 55 }
 56 //乘法,采用加法模拟,避免中间结果超出LL
 57 LL multi(LL a,LL b,LL mod)
 58 {
 59     LL ans=0;
 60     while(b)
 61     {
 62         if(b & 1)
 63         {
 64             b--;
 65             ans=(ans+a) % mod;
 66         }
 67         else
 68         {
 69             b/=2;
 70             a=(2*a) % mod;
 71         }
 72     }
 73     return ans;
 74 }
 75
 76 //快速幂,同样避免超出LL的做法
 77 LL Pow(LL a, LL b, LL mod)
 78 {
 79     LL ans=1;
 80     while(b)
 81     {
 82         if(b&1)
 83         {
 84             b--;
 85             ans=multi(ans,a,mod);
 86         }
 87         else
 88         {
 89             b/=2;
 90             a=multi(a,a,mod);
 91         }
 92     }
 93     return ans;
 94 }
 95
 96 //miller_rabin的一遍探测,返回false表示是合数
 97 bool witness(LL a,LL n)
 98 {
 99     LL d=n-1;
100     while( !(d&1) )
101         d >>= 1;
102     LL t=Pow(a, d, n);
103     while(d!=n-1 && t!=1 && t!=n-1)
104     {
105         t=multi(t,t,n);
106         d<<=1;
107     }
108     return t==n-1 || d&1;
109 }
110
111 //miller_rabin算法,返回false表示是合数,否则是素数
112 //返回素数出错的概率(最高)为 1 / (4 ^ times)
113 bool miller_rabin(LL n)
114 {
115     if(n == 2)
116         return true;
117     if( n<2 || !(n&1) )
118         return false;
119     for(int i = 1; i <= Times ; i++ )
120     {
121         LL a = random(n-2) + 1;
122         if( !witness(a, n) )
123             return false;
124     }
125     return true;
126 }
127
128
129 //************************************************
130 //pollard_rho 算法进行质因数分解
131 //************************************************
132 LL factor[100];//质因数分解结果(刚返回时是无序的)
133 int tol;//质因数的个数。数组小标从0开始
134
135 LL gcd(LL a,LL b)
136 {
137     if(a==0)return 1;//???????
138     if(a<0) return gcd(-a,b);
139     while(b)
140     {
141         LL t=a%b;
142         a=b;
143         b=t;
144     }
145     return a;
146 }
147
148 LL Pollard_rho(LL x, LL c)
149 {
150     LL i=1,k=2;
151     LL x0=rand()%x;
152     LL y=x0;
153     while(1)
154     {
155         i++;
156         x0=(multi(x0, x0, x) + c) % x;
157         LL d=gcd(y-x0,x);
158         if(d!=1&&d!=x) return d;
159         if(y==x0) return x;
160         if(i==k){y=x0;k+=k;}
161     }
162 }
163
164 //对n进行素因子分解
165 void findfac(LL n)
166 {
167     if(miller_rabin(n))//素数
168     {
169         factor[tol++]=n;
170         ans = MIN(ans, n);
171         return;
172     }
173     LL p=n;
174     while(p>=n)
175         p=Pollard_rho(p, rand()%(n-1)+1);
176     findfac(p);
177     findfac(n/p);
178 }
179
180
181
182 int main()
183 {
184     //FOPENIN("in.txt");
185     while(~scanf("%d", &t))while(t--)
186     {
187         ans = inf;
188         scanf("%I64d", &n);
189         findfac(n);
190         if(miller_rabin(n))
191             printf("Prime\n");
192         else printf("%I64d\n", ans);
193     }
194     return 0;
195 }

POJ 1811Prime Test(米勒拉宾素数测试),布布扣,bubuko.com

时间: 2024-08-02 07:00:21

POJ 1811Prime Test(米勒拉宾素数测试)的相关文章

csu 1552(米勒拉宾素数测试+二分图匹配)

1552: Friends Time Limit: 3 Sec  Memory Limit: 256 MBSubmit: 723  Solved: 198[Submit][Status][Web Board] Description On an alien planet, every extraterrestrial is born with a number. If the sum of two numbers is a prime number, then two extraterrestr

Miller_Rabin(米勒拉宾)素数测试

2018-03-12 17:22:48 米勒-拉宾素性检验是一种素数判定法则,利用随机化算法判断一个数是合数还是可能是素数.卡内基梅隆大学的计算机系教授Gary Lee Miller首先提出了基于广义黎曼猜想的确定性算法,由于广义黎曼猜想并没有被证明,其后由以色列耶路撒冷希伯来大学的Michael O. Rabin教授作出修改,提出了不依赖于该假设的随机化算法. 问题描述:对于大整数N,判断其是否为素数. 问题求解: 若N为偶数,直接返回false,若N是奇数,则进行以下几步进行判断: 将N -

Miller_Rabin(米勒拉宾)素数测试算法

首先需要知道两个定理: 1: 费马小定理: 假如p是素数,且gcd(a,p)=1,那么 a(p-1)≡1(mod p). 2:二次探测定理:如果p是素数,x是小于p的正整数,且,那么要么x=1,要么x=p-1. 证明:这是显然的,因为相当于p能整除,也即p能整除(x+1)(x-1). 由于p是素数,那么只可能是x-1能被p整除(此时x=1) 或 x+1能被p整除(此时x=p-1). 接着 如果a^(n-1) ≡ 1 (mod n)成立,Miller-Rabin算法不是立即找另一个a进行测试,而是

米勒-拉宾素性测试学习

之前一直对于这个神奇的素性判定方法感到痴迷而又没有时间去了解.借着学习<信息安全数学基础>将素性这一判定方法学习一遍. 首先证明一下费马小定理. 若p为素数,且gcd(a, p)=1, 则有 a^(p-1) = 1 (mod p) 基于以下定理 若(a, p)=1,{x| (x, p)=1}为模p下的一个完全剩余系,则{ax| (x, p)=1}也为模p下的一个完全剩余系. 又{0, 1, 2, ... p-1}为模p下一个剩余系   因此有, {a*0, a*1, a*2, ... a*(p

米勒-拉宾(MillerRabbin)素性测试算法

首先,在了解米勒-拉宾素性测试之前,我们要先了解费马小定理. 关于费马小定理就不再细说原理和证明了,应用非常广泛. 费马小定理中说  若p是质数  则有 a的(p-1)次方在(mod p)的情况下 恒等于1   数学表达式--->  a^(p-1) ≡ 1 (mod p) 然后我们要注意: p若是质数  则满足费马小定理  但是  满足费马小定理  并不能证明p就是质数 有些数字 满足费马小定理,但是并不是质数  他们叫做伪质数(伪素数的个数是无穷的) 那么 知道了这些  算法就很好理解了 一个

2018 ACM-ICPC 中国大学生程序设计竞赛线上赛 B. Goldbach-米勒拉宾素数判定(大素数)

若干年之前的一道题,当时能写出来还是超级开心的,虽然是个板子题.一直忘记写博客,备忘一下. 米勒拉判大素数,关于米勒拉宾是个什么东西,传送门了解一下:biubiubiu~ B. Goldbach 题目传送门 自己看题意吧,直接贴代码了. 代码: 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<cstdlib> 6 #i

HDU 2138 How many prime numbers (判素数,米勒拉宾算法)

题意:给定一个数,判断是不是素数. 析:由于数太多,并且太大了,所以以前的方法都不适合,要用米勒拉宾算法. 代码如下: #include <iostream> #include <cstdio> #include <algorithm> #include <queue> #include <vector> #include <cstring> #include <map> #include <cctype> u

HDU 4910 Problem about GCD(米勒拉宾)

HDU 4910 Problem about GCD 题目链接 题意:给定一个数字,求出1 - n之间与他互质的数的乘积mod n 思路:看了网上别人找出来的规律,原文链接 然后由于这题的n很大,也没法直接判定,可以这样搞,先去试10^6以内的素数,判断可不可以,如果不行,再利用米勒拉宾判下是否是素数,如果不是的话,把这个数字开根在平方,判断是不是完全平方数,这样做的原因是数字最大10^18,如果没有10^6以内的质因子,又不是质数的话,那么他最多只能包含2个质因子了,那么如果他不是一个完全平方

HDU2138 &amp; 米勒拉宾模板

题意: 给出n个数,判断它是不是素数. SOL: 米勒拉宾裸题,思想方法略懂,并不能完全理解,所以实现只能靠背模板.... 好在不是很长... Code: /*========================================================================== # Last modified: 2016-03-21 10:09 # Filename: miller-rabin.cpp # Description: =================