算法学习笔记1.3.2 素数判定

任务

给一个正整数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

原文地址:https://www.cnblogs.com/zifeiy/p/9526291.html