大素数检测: Miller_Rabin算法

本文介绍了一种解决哥德巴赫猜想的方法,即任一大于5的整数可以写成三个质数之和。文章通过埃拉托斯特尼筛法找出小范围内的质数,并使用Miller-Rabin算法验证较大数的素性。

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

2021年ACM竞赛班训练(三)

A题: 验证哥德巴赫猜想

原题链接

思路:

1、原初哥德巴赫猜想的现代陈述为:任一大于5的整数都可以拆成三个质数之和。通过观察样例输入,不妨假设输入 n n n足够大时: n = a + b + c n = a + b + c n=a+b+c 其中 a , b a, b a,b 在小质数内可实现 ( a , b ∈ ( 2 , 600 ) a,b \in (2, 600) a,b(2,600),可利用(埃拉托斯特尼)筛法得到该范围内素数表).

2、对于较大数 c = n − a − b c = n - a - b c=nab 的素性判断考虑Miller-Rabbin算法.

代码:

#include <bits/stdc++.h>
#define LL long long
using namespace std;

LL pl[601]; //用来装筛法得到的素数pl[i] = 0表示素数,pl[i] = 1表示被筛掉的合数。

//qmul用于计算两数的积,定义该函数目的是防溢出
LL qmul(LL x, LL y, LL mod) { 
    return (x * y - (long long)(x / (long double)mod * y + 1e-3) *mod + mod) % mod;
}
//快速幂算法
LL qpow(LL a, LL n, LL mod) {
    LL res = 1, tmp = a;
    for(LL i = n; i; i >>= 1){
        if(i&1) res = (res*tmp)%mod;
        tmp = (tmp*tmp) %mod;
    }
    return res;
}
//Miller_Rabin算法
LL prime[6] = {2, 3, 5, 233, 331}; 
bool Miller_Rabin(LL p) {
    if(p < 2) return 0;
    if(p != 2 && p % 2 == 0) return 0;
    LL s = p - 1;
    while(! (s & 1)) s >>= 1;
    for(int i = 0; i < 5; ++i) {
        if(p == prime[i]) return 1;
        LL t = s, m = qpow(prime[i], s, p);
        while(t != p - 1 && m != 1 && m != p - 1) {
            m = qmul(m, m, p);
            t <<= 1;
        }
        if(m != p - 1 && !(t & 1)) return 0;
    }
    return 1;
}

void solve(LL num) {
	//当a, b, c中a, b为小范围内的素数且c(=n-a-b)通过Miller_Rabin检测时即为答案输出
    for(int i = 2; i <= 600; i++) {
        for(int j = i; j <= 600; j++) {
            if(pl[i] == 0 && pl[j] == 0 && Miller_Rabin(num - i - j)) {
                printf("%d %d %lld\n", i, j, num - i -j);
                return;
            }
        }
    }
}

int main() {
	//埃拉托斯特尼筛法实现
    for(int i = 2; i <= sqrt(600) + 1; i++) {
        if(!pl[i]) for(int j = i*i; j <= 600; j+=i) {
            pl[j] = 1;
        }
    }
	
	//读取数据
    LL num;
    while(~scanf("%lld", &num)) {
        solve(num);
    }
    return 0;
}

Miller_Rabin算法:

已知:

(1)费马定理:
a p − 1 = 1 ( m o d   p ) a^{p-1} = 1 (mod\,p) ap1=1(modp)
其中 p p p为质数, a a a不是 p p p的倍数
(2)二次探测定理:
x 2 ≡ 1 ( m o d   p ) ⇒ x = 1   o r   x = p − 1 x^2 \equiv 1 (mod\,p) \Rightarrow x = 1 \,or\, x = p-1 x21(modp)x=1orx=p1

简要证明:

n n n是奇素数,则 n − 1 n-1 n1必为偶数。令 n − 1 = 2 q m n-1 = 2^qm n1=2qm.
∀ a ∈ ( 1 , n ) \forall a \in (1, n) a(1,n), 利用费马定理知, ( a 2 q m = a n − 1 ) ≡ 1 ( m o d   n ) (a^{2^qm} = a ^{n-1}) \equiv 1 (mod\,n) (a2qm=an1)1(modn)
由二次探测定理可知: a 2 q − 1 m ≡ 1 ( m o d   n ) a^{2^{q-1}m} \equiv 1 (mod\,n) a2q1m1(modn) a 2 q − 1 m ≡ n − 1 ( m o d   n ) . a^{2^{q-1}m} \equiv n - 1(mod\,n). a2q1mn1(modn).
a 2 q − 1 m ≡ 1 ( m o d   n ) a^{2^{q-1}m} \equiv 1 (mod\,n) a2q1m1(modn)成立,则再次由二次探测定理可知:
a 2 q − 2 m ≡ 1 ( m o d   n )   a^{2^{q-2}m} \equiv 1 (mod\,n)\, a2q2m1(modn)   a 2 q − 2 m ≡ n − 1 ( m o d   n ) \,a^{2^{q-2}m} \equiv n-1(mod\,n) a2q2mn1(modn)
⋯ \cdots 。反复利用刺耳探测定理直到:
a m ≡ 1 ( m o d   n )   a^{m} \equiv 1 (mod\,n)\, am1(modn) a m ≡ n − 1 ( m o d   n ) a^{m} \equiv n-1 (mod\,n) amn1(modn)
综上:如果 n n n是素数,则必有 a m = 1   ( m o d   n ) a^m = 1\,(mod\,n) am=1(modn),或存在 a 2 r m ≡ n − 1 ( m o d   n ) r ∈ [ 0 , q − 1 ] a^{2^rm} \equiv n-1(mod\,n)\quad r \in [0, q-1] a2rmn1(modn)r[0,q1]而使二次检测不能传递到 m m m

算法应用

1、给定(input)奇数 n n n, 为判断其素性,先测试 a 2 p m ≡ 1 ( m o d   n ) a^{2^pm} \equiv 1(mod\,n) a2pm1(modn)是否成立。若不成立则 n n n必为合数,若成立需要进一步测试。
2、考虑对于Miller序列:
a m   ( m o d   n ) , a 2 m   ( m o d   n ) , a 4 m   ( m o d   n ) , ⋯   , a 2 q m   ( m o d   n ) a^m\,(mod\,n), a^{2m}\,(mod\,n),a^{4m}\,(mod\,n), \cdots, a^{2^qm}\,(mod\,n) am(modn),a2m(modn),a4m(modn),,a2qm(modn),若 a m   ( m o d   n ) a^m\,(mod\,n) am(modn) 成立,或存在 a 2 r m ≡ n − 1 ( m o d   n ) r ∈ [ 0 , q − 1 ] a^{2^rm} \equiv n-1(mod\,n)\quad r \in [0, q-1] a2rmn1(modn)r[0,q1] 则认为n通过Miller_Rabin测试。

注意:1、Miller_Rabin是素数的必要条件,即素数一定可以通过Miller_Rabin测试,不能通过Miller_Rabin的数必为合数。
2、Miller_Rabin不是素数的充分条件,即通过该测试的数可能不是素数。但该算法给出错误结果的概率 p ( k ) ≤ ( 1 4 ) k p(k) \leq (\frac{1}{4})^k p(k)(41)k其中 k k k为测试次数。在实际应用中,效果往往好得多!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值