任务
给一个正整数N,判定N是否为素数。
说明
Miller-Rabin测试:要测试N是否为素数,首先将N-1分解为2^s*d。在每次测试开始时,先随机选一个介于[1,N-1]的整数a,如果对所有在区间[0,s-1]范围内的r都满足a^d mod N <> 1 且 a ^ (2 ^ r * d) mod N <> -1,则N是合数。否则,N有3/4的几率为素数。为了提高测试的正确性,可以选择不同的a进行多次测试。
接口
bool isPrime(int N);
复杂度:O(logN)
输入:N 待测试的整数
输出:False表示为合数,True表示有很大概率为素数。
代码
#include <iostream>
using namespace std;
long long pow_mod(long long a, long long i, long long n) {
if (i == 0) return 1 % n;
long long temp = pow_mod(a, i>>1, n);
temp *= temp;
if (i & 1) temp = temp * a % n;
return temp;
}
bool test(int n, int a, int d) {
if (n == 2 || n == a) return true;
if ( (n&1) == 0) return false;
while ( !(d&1) ) d >>= 1;
int t = pow_mod(a, d, n);
while ( d != n -1 && t != 1 && t != n-1 ) {
t = (long long) t * t % n;
d <<= 1;
}
return ( t == n-1 || (d & 1) == 1 );
}
bool isPrime(int n) {
if (n < 2) return false;
int a[] = {2, 3, 5}; // 测试集,更广泛的测试范围需要更大的测试集
for (int i = 0; i <= 2; i ++)
if (!test(n, a[i], n-1)) return false;
return true;
}
int main() {
for (int i = 2; i <= 100; i ++) {
if (isPrime(i)) cout << i << endl;
}
return 0;
}
使用范例
HDU2138