素数的求解方法:

本文详细介绍了几种求解素数的方法,包括朴素判断、Miller-Rabin素性测试、筛选法、容斥原理和Meissel-Lehmer算法。通过这些算法,可以从不同角度高效地找出素数,如O(sqrt(n))的试除法,随机测试的Miller-Rabin算法,线性筛选的埃拉托斯特尼筛法,以及适用于大数场景的Meissel-Lehmer算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、朴素判断素数算法

就判断素数而言,事实上是非常简单的了。根据定义,判断一个整数n是否是素数,只需要去判断在整数区间[2, n-1]之内,是否具有某个数m,使得n % m == 0。代码可以这么写:

int isPrime(int n) {  
    int i;  
    for (i = 2; i < n; ++i) {  
        if (n % i == 0) return 0;  
    }  
    return 1;  
} 

事实上,这个算法是O(n)的,感觉是很快了,但是依旧无法满足需求。所以有一个算法是O(sqrt(n))的算法。代码可以这么写:

int isPrime(long long n) {  
    long long i;  
    for (i = 2; i * i <= n; ++i) {  
        if (n % i == 0) return 0;  
    }  
    return 1;  
}  

原理很巧妙,也仅仅是把代码的i < n变成了i * i <= n而已,但是优化却是极其高的。可能你会注意到,在上一份代码里面,我定义的n为int类型,而后面一份代码,我却定义成了long long,这是因为在1s内,上一份代码能判断出来的数量级为1e8,而后面一份代码判断出来的数量级却几乎可以达到1e16。而原因仅仅是因为a * b = c的话一旦a是c的约数,那么b也是,如果a不是,那么b也不是。
这个方法也可以称作试除法。

二、Miller_Rabin素性测试

尽管上面的O(sqrt(n))的算法已经非常优秀了,但是面对更高数量级的“大数”却会显得力不从心。而这个时候,Miller_Rabin的优越性就显示出来了。
Miller_Rabin的理论基础来源于费马小定理。值得一提的是费马小定理是数论四大定理之一。

费马小定理:n是一个奇素数,a是任何整数(1≤ a≤n-1) ,则 a^(n-1)≡1(mod n)
要测试n是否是一个素数,首先将n-1分解为(2^s) * d,在每次测试开始时,先随机选择一个介于[1, N - 1]的整数a,之后如果对于所有的r∈[0, s - 1],若a^d mod N ≠ 1且a^((2^r) * d) mod N ≠ -1,那么n就是一个合数,否则n有3/4的几率是素数。

这也是为什么说这个算法只是素性测试了,他不能完全保证结果正确,但是当测试次数大约为20的时候,基本可以确保正确率达到97%以上。
它的代码可以这么写:

const int S = 20;  
LL mod_mul(LL a, LL b, LL n) {  
    LL res = 0;  
    while (b) {  
        if (b & 1) res = (res + a) % n;  
        a = (a + a) % n;  
        b >>= 1;  
    }  
    return res;  
}  
LL mod_exp(LL a, LL b, LL n) {  
    LL res = 1;  
    while (b) {  
        if (b & 1) res = mod_mul(res, a, n);  
        a = mod_mul(a, 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值