浅谈基于随机性算法的素数判定
2016-09-12 22:13
253 查看
引:考虑这样的一个问题
判断一个long long范围内的数是否是素数。引理1-1:
ap≡a(modp)|(a,p)=1
其实这就是熟悉的Fermat小定理了~~
引理1-2:
对于
a2≡1(modn)|n为素数
的解仅有 a = 1 或 a = n - 1
显然原式 = (a mod n) * (a mod n)
所以当且仅当 a mod n = 1 或 a mod n = -1 时有解, 那么显然~~~
下面介绍一种基于随机算法的Miller-Robin算法
1.将n - 1分解成 2 ^ q * m 的形式
2.若n为大于2的素数,则必定存在 a < n 使得 a ^ (n-1) mod n = 1
3.先随机取一个a,计算 a ^ m ,然后再在 a ^ m 的基础上不停地平方,并使得 a 的指数小于等于 n - 1, 若a ^ (n-1) mod n = 1, 则在这个过程中必然会算出某个值同余 n 为 1,我们就找到了答案。
4.注意进行多重判断(多选几个a)。
下面是代码(poj 1811):
#include<algorithm> #include<iostream> #include<cstdio> #include<vector> #include<cmath> using namespace std; typedef long long LL; const LL INF = 1LL << 60; #define debug(...) fprintf(stderr, __VA_ARGS__) LL gcd(LL a, LL b) { if(a > b) swap(a, b); return a == 0 ? b : gcd(b % a, a); } LL Mul(LL n, LL m, LL p) { LL ans = 0; for(LL i = 1; i <= m; i <<= 1LL, n = (n + n) % p) if(i & m) ans = (ans + n) % p; return ans; } LL Pow(LL n, LL m, LL p) { LL ans = 1; n %= p; while(m > 0LL) { if(m & 1LL) ans = Mul(ans, n, p); n = Mul(n, n, p); m >>= 1LL; } return ans; } bool isprime(LL n, LL t) { if(n == 2 || n == 3) return true; if(n < 2 || (n & 1LL) == 0) return false; LL m = n - 1, q = 0; while((m & 1LL) == 0) { q++; m &g aefa t;>= 1LL; } for(LL i = 0; i < t; i++) { LL a = rand() % (n - 1) + 1; LL x = Pow(a, m, n), y; for(LL j = 0; j < q; j++) { y = Mul(x, x, n); if(y == 1 && x != 1 && x != n - 1) return false; x = y; } if(x != 1) return false; } return true; } LL Min; void Pollcard_Rho(LL n) { //debug("%lld\n", n); if(isprime(n, 40)) { Min = min(Min, n); return; } while(1) { LL x = rand() % (n - 1) + 1; LL c = rand() % (n - 1) + 1; for(LL y = x, i = 2, j = 2; ; i++) { x = (Mul(x, x, n) + c) % n; LL z = (y - x) % n; if(z < 0) z = -z; LL d = gcd(z, n); if(d > 1 && d < n) { Pollcard_Rho(d), Pollcard_Rho(n / d); return; } if(x == y) break; if(i == j) y = x, j <<= 1; } } } LL n, T; int main() { #ifndef ONLINE_JUDGE freopen("data.txt", "r", stdin); freopen("ans.txt", "w", stdout); #endif srand(67); scanf("%lld", &T); while(T--) { scanf("%lld", &n); if(isprime(n, 40)) puts("Prime"); else { Min = INF; Pollcard_Rho(n); printf("%lld\n", Min); } } return 0; }
题中还涉及到了另一个基于随机性的因数分解(其实就是一个瞎逼乱搞神奇算法, 时间复杂度 O(玄学))。
相关文章推荐
- 九度OJ-题目1047 素数判定
- 素数判定
- LG 的数学计划 ---- 第一步 素数判定
- B - 素数判定 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
- CODEVS 1430 素数判定
- 综合实践九1000判定素数AC
- 浅谈基于IP网络的H.264关键技术及应用
- 素数判定
- hdu 2012 素数判定 xy之间的整数表达式素数 20140723.cpp
- 浅谈基于Selenium的Web自动化测试框架
- 【2012 素数判定】
- 模板:(数论:大素数判定-分解: Miller-Rabin算法)
- 浅谈基于JavaScript的DDOS攻击
- How many prime numbers HDU - 2138(素数判定)
- 大素数判定,大整数因式分解模板 HDU 4910
- ACM-2012 素数判定
- CF735D Taxes 哥德巴赫猜想\判定素数 \进一步猜想
- 【世界数学难题】素数判定与大数因子分解问题(下)