标签:
Theorem 素数有无限多个
Proof. 若存在最大素数P_max , 设 X = (P_1 * P_2 …… * P_max) + 1,此时如果X为素数, 则X > P_max, 矛盾, 如果X为合数, 则必存在它的一个素因子 P_X 且 P_X > P_max, 矛盾。
Theorem
显然是在越大的范围内分布得越稀疏的。
暴力的方法即枚举每个小于n的数位约数, 简单的优化即 枚举 2~sqrt(n) 的所有质数。
由于一些伪素数令费马小定理的逆定理不成立, 而去背一张伪素数表又不是很优美, miller-rabin 算法随之产生。
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
强伪素数
设n是一个大于4的奇整数,s和t是使得(n-1)=2^s*t的正整数,其中t为奇数,设B(n)是如下定义的整数集合:
a属于集合B(n)当且仅当2≤a≤n-2且
1: a^tmodn=1
2: 存在整数i,0<=i<s满足a^((2^i)*t) mod n=n-1
当n为素数时, 任意a在2和n-1中,均有a属于集合B(n)
当n为合数时,若a属于集合B(n),则称n为一个以a为底(基)的强伪素数,称a为n素性的强伪证据。
n为素数,说明它对所有底均为强伪素数
Btest(a,n){
//n为奇数,返回true。即返回真说明n是强伪素数
s←0; t ←n-1; //t开始为偶数
repeat
s++;t ← t÷2;
until t mod 2 = 1; //n-1=2st t为奇数
x ←at mod n;
if x=1 or x=n-1 then return true; //满足①or②。
for i ←1 to s-1 do{
x ←x2 mod n;
if x=n-1 then return true; //满足②,
}
return false;}
通过这一定义则发现,小于1000的奇合数中,随机选到一个强伪证据的概率小于1%
更重要的是,对任一奇合数,强伪证据比例都很小
所以,我们可以多次运行下面的算法,就可把错误概率降低我们可控制的范围
MillRab(n) { //奇n>4,返回真时表示素数,假表示合数
a←uniform(2..n-2);
return Btest(a,n); //测试n是否为强伪素数
}//该算法是3/4-正确,偏假的。
RepeatMillRob(n,k){
for i ←1 to k do
if MillRob(n) =false then
return false; //一定是合数
return true;
}
虽然miller-rabin 是一个随机性算法, 但是取前9个素数就可以保证在 10^18范围内的正确性了。
代码很简单
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #define ll long long using namespace std; int t, prim[15] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23}; ll u; ll mypow(ll x, ll k, ll mod){ ll ret = 1; while(k){ if(k & 1) (ret *= x) %= mod; (x *= x) %= mod; k >>= 1; }return ret; } bool MR(ll a, ll n){ if(a >= n) return 1; ll w = mypow(a, u, n); if(w == 1) return 1; for(int i = 0; i < t; i ++){ if(w == n - 1) return 1; (w *= w) %= n; } return 0; } bool pd(ll n){ if(n == 2) return 1; if(n < 2 || (!(n & 1))) return 0; t = 0; u = n - 1; while((u & 1) == 0) u >>= 1, t ++; for(int i = 1; i <= 9; i ++) if(!MR(prim[i], n)) return 0; return 1; } int main(){ int N; while(scanf("%d", &N) != EOF){ int cnt = 0; for(int i = 1; i <= N; i ++){ ll x; scanf("%I64d", &x); if(pd(x)) cnt ++; } printf("%d\n", cnt); } return 0; }
标签:
原文地址:http://www.cnblogs.com/lixintong911/p/4380039.html