素数筛法和测试
来源:互联网 发布:vc socket编程 并发 编辑:程序博客网 时间:2024/05/19 11:45
一。筛法
线性时间筛法:
一边制作质数表,一边删掉每个数的质数倍,时间复杂度就能达到O(N) 。
const int N = 20000000 ;bool sieve [ N ]; void eratosthenes (){ vector < int > prime ; for ( int i = 2 ; i < N ; i ++) { if (! sieve [ i ]) prime . push_back ( i ); for ( int j = 0 ; i * prime [ j ]< N ; j ++) { sieve [ i * prime [ j ]] = true ; if ( i % prime [ j ] == 0 ) break ; } }}
6n±1 Method
原理是:只拿2 和3 这两个质数先筛过一遍,剩下的数字则用试除法验证是不是质数。
2 和3 的最小公倍数是6 ,我们就把所有数字分为6n 、 6n+1 、 6n+2 、 6n+2 、 6n+3 、 6n+4 、 6n+5 六种( n 是倍率)。除以六会余零的数字为6n ,除以六会余一的数字为6n+1 ,以此类推。
可以看出6n 、 6n+2 、 6n+3 、 6n+4 会是2 或3 的倍数,不属于质数。因此,只要验证6n+1 和6n+5 是不是质数就可以了。( 6n+5 也可以写成6n-1 ,意义不变。)
6n-1 到6n+1 ,再到下一个6n-1 ,再到6n+1 ,把这些要验证的数字由小排到大,可以发现之间的差值会是2 4 2 4 2 4 . .. 不断跳二跳四。实作程式码时,就可以直接用加法加二加四,而不必用乘法及加减法计算6n-1 、 6n+1 ,如此一来程式的执行效率会好一点。
验证的顺序是:数字2 和3 明显的是质数,不必验证;若是从数字5 开始验证,那么下一个要验证的数字就是5+2 ,再下一个就是5+2+4 ,再下一个就是5+2+4+2 ,如此不断下去。
// 以试除法判断质数bool isprime ( int n ){ for ( int i = 5 ; i * i <= n ; i += 2 ) if ( n % i == 0 ) return false ; return true ;} // 只检查6n±1。这些数字的间隔为2 4 2 4....void make_prime (){ cout << "找到质数2" ; cout << "找到质数3" ; for ( int i = 5 , gap = 2 ; i < 1000000 ; i += gap , gap = 6 - gap ) if ( isprime ( i )) cout << "找到质数" << i ;}二。质数测试,测试一个数字是否为质数。
整除性测试法。
依照质数定义,一个质数p 不会被大于1 且小于p 的数字整除,只要把这些数字都拿来试除,就可以判定一个数字是不是质数。
bool divisibiity_test ( int n ){ // 穷举n所有可能的因数一一试除。 for ( int d = 2 ; d < n ; ++ d ) if ( n % d == 0 ) return false ; //不是质数 return true ; //是质数}
bool divisibiity_test ( int n ){ // 一个数字n不会有大于sqrt(n)的质因数(除了n本身以外) int sqrt_n = sqrt ( n ); for ( int d = 2 ; d <= sqrt_n ; ++ d ) if ( n % d == 0 ) return false ; return true ;}
费玛小定理:
若n是质数,a小于n,则a^n ≡ a (mod n)。
若n是质数,a小于n,a不是零,则a^(n-1) ≡ 1 (mod n)。
费玛质数测试法是运用费玛小定理而想出的方法:
n是质数,费玛小定理一定成立:a^(n-1) % n = 1一定成立。
n是合数,费玛小定理可能成立:a^(n-1) % n = 1可能成立。
当a^(n-1) % n = 1成立,就推定n是质数。
此算法的结果不一定正确。通过测试的数字,可能是合数或质数;无法通过测试的数字,一定是合数。
bool fermat_primality_test ( int n ){ // 随便取得一个数值当作a, // 但是必须大于1、小于n,才有意义。// srand(time(0)); int a = rand () % ( n - 2 ) + 2 ; // 计算a^(n-1) % n的值,存于x中。 int x = 1 ; for ( int i = 1 ; i < n ; ++ i ) x = x * a % n ; return x == 1 ;// return pow(a, n-1, n) == 1;}
Miller-Rabin Algorithm
此算法的结果不一定正确。通过测试的数字,可能是合数或质数;无法通过测试的数字,一定是合数。
bool miller_rabin ( int n ){ if ( n < 2 ) return false ; // srand(time(0)); int a = rand () % ( n - 2 ) + 2 ; int u = n - 1 , t = 0 ; while ( u % 2 == 0 ) u >>= 1 , t ++; int x = pow ( a , u , n ); // x = a ^ u % n; if ( x == 1 || x == n - 1 ) return true ; for ( int i = 0 ; i < t - 1 ; i ++) { x = mul ( x , x , n ); // x = x * x % n; if ( x == 1 ) return false ; if ( x == n - 1 ) return true ; } return false ;}
- 素数筛法和测试
- 素数生成和素数测试--筛选法
- 素数判断和素数筛法
- MILLer素数测试法
- hdu 2098 分拆素数和(素数筛法)
- O(NloglogN)素数筛法与O(N)素数筛法的对比测试
- 主元素问题和素数测试
- Miller_Rabin 算法进行素数测试和分解
- 随机素数测试和大数分解
- 大范围素数筛法性能测试(2^64)
- 素数测试
- 素数测试
- 素数测试
- 素数测试
- 素数测试
- 素数测试
- 素数测试
- 素数筛和优化
- 坑爹的底层
- CListCtrl控件主要事件及LVN_ITEMCHANGED消息和鼠标双击列表项事件的处理
- AbstractFactory抽象工厂模式
- cocos 事件转发1
- Windows同步API—— Mutex
- 素数筛法和测试
- Java中Properties类的使用(转)
- 基于注解风格的Spring-MVC的拦截器
- gsoap向java webserverce传输中文乱码问题
- jsp输入限制正则表达式
- JAVA基础之理解JNI原理
- stream_set_blocking让程序无阻塞
- C++学习[2]--字符串和字符串数组的思考
- ln命令:硬链接和符号链接