poj 1811 (prime test)

来源:互联网 发布:es海量数据分析 编辑:程序博客网 时间:2024/05/17 22:52

POJ - 1811


Prime Test
Time Limit:6000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u

SubmitStatus

Description

Given a big integer number, you are required to find out whether it's a prime number.

Input

The first line contains the number of test cases T (1 <= T <= 20 ), then the following T lines each contains an integer number N (2 <= N < 254).

Output

For each test case, if N is a prime number, output a line containing the word "Prime", otherwise, output a line containing the smallest prime factor of N.

Sample Input

2510

Sample Output

Prime2


题意:输入T个n, 如果n是质数,输出Prime,否则输出n的最小质因子


本题使用Miller_Rabin判质数方法,它的依据为费马小定理,取若干个a进行验证,如果中间结果以及结果皆为1,则认为x为质数

还有算约数的方法,本质是: 随机一个值,让它在某个规则下出现环\


(下方来自段大神)

题意:T个数,若为素数则输出Prime,否则输出其最小的质因子。
思路:
(1)素数判定(Miller-Robin):
根据费马小定理,有:
a ^ (p - 1) % p = 1;
其中p为素数,0 < a < p。
于是我们随机生成a,验证p是否满足条件即可,为了尽量减少错误概率,可以生成多个不同的a。
(2)质因数分解(Pollard-Rho):
依旧是随机算法,设 1 < x, y < n, (x, y为随机生成)
每次判断t = gcd(|x - y|, n)是否为1, 若不是则t为n的一个因数,递归分解 t 与 n / t,并判断是否已分解为素数(研究表明,|x - y|比 x 更不容易与n互质,虽然不会证->__->);
若互质,则令x = (x * x + c) % n, 可以证明x必定会出现循环,所以用y来判断是否重复,如果出现了循环却还未找到因数,再随机出个c继续判断即可。



#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>using namespace std;#define LL long long#define MAXN (100+5)LL ans;LL X[MAXN];LL multi(LL x, LL y, LL n){LL ret = 0;while(y){if(y & 1LL) ret = (ret+x) % n;x = (x+x) % n;y >>= 1;}return ret;}LL Base(LL x, LL y, LL n){LL ret = 1LL;while(y){if(y & 1LL) ret = multi(ret, x, n);x = multi(x, x, n);y >>= 1;}return ret;}bool Miller_Rabin(LL n){if(n == 2) return true;LL s = 20, t = 0, u = n-1;while(!(u&1)){t++; u >>= 1;}while(s--){LL a = rand()%(n-1) + 1;X[0] = Base(a, u, n);for(LL i = 1; i <= t; i++){X[i] = multi(X[i-1], X[i-1], n);if(X[i] == 1 && X[i-1] != 1 && X[i-1] != (n-1)) return false;}if(X[t] != 1) return false;}return true;}LL gcd(LL a, LL b){return !b? a: gcd(b, a%b);}LL Pollard_Rho(LL n, LL c){LL i = 1LL, k = 2LL, x = rand()%(n-1)+1, y = x;while(true){i++;x = (multi(x, x, n) + c) % n;LL p = gcd((y-x+n)%n, n);if(p != 1 && p != n) return p;if(x == y) return n;if(i == k){y = x;k <<= 1;}}}void find(LL n, LL c){//printf("n = %lld\n", n);if(n == 1) return;if(Miller_Rabin(n)){ans = min(ans, n);return;}//printf("yes!\n");LL p = n, k = c;while(p == n) p = Pollard_Rho(p, c--);find(p, k); find(n/p, k);}int main(){//freopen("test.in", "r", stdin);int T;scanf("%d", &T);while(T--){LL n;scanf("%lld", &n);ans = (1LL<<62);find(n, 120);if(ans == n) printf("Prime\n");else printf("%lld\n", ans);}return 0;}



1 0
原创粉丝点击