我似乎发现了一种很新的素数筛法

作者分享了在OI课程中通过观察素数规律,发现的一种新算法,利用2和3的关系简化素数判断,提出廿四筛,虽然时间复杂度较欧拉筛稍慢,但具有启发性。

事情是这样的:今天上OI课程,snowycat讲解STL 的算法,突然就讲到了欧拉筛,当时还有一会儿就下课了,所以我就开了会儿小差(什么逻辑?)就开始写素数的式子,感觉突然发现了一种很新的算法,认为值得写一下,毕竟如果是已经出现的,就当头脑风暴,如果没出现,率先发现也很nice对吧!

我们先来看100以内的素数:

2、3、5、7、11、13、17、19、23、29、31、37、41、43、47、53、59、61、67、71、73、79、83、89、97

除了2和3以外,我们不难发现,其实每一个素数都可以表示为含有2和3的关系式:

2 = breakI
3 = breakII
7 = 2*3+1; first
11 = 2*3*2-1; second
13 = 2*3*2+1; first
17 = 2*3*3-1; second
19 = 2*3*3+1; first
23 = 2*3*4-1; second
29 = 2*3*5-1; second
31 = 2*3*4+1; first
37 = 2*3*6+1; first
41 = 2*3*7-1; second
43 = 2*3*7+1; first
47 = 2*3*8-1; second
53 = 2*3*9-1; second
59 = 2*3*10-1; second
61 = 2*3*10+1; first
67 = 2*3*11+1; first
71 = 2*3*12-1; second
73 = 2*3*12+1; first
79 = 2*3*13+1; first
83 = 2*3*14-1; second
89 = 2*3*15-1; second
97 = 2*3*16+1; first
如果拓展到n
那就是
I:
(n + 1) % 6 == 0;
II:
(n - 1) % 6 == 0;

我所定义的first和second指的是后面是加法还是减法

如果说我们定义上flag,那就可以发现2和3其实是边界,而其实素数应该满足上面I和II的表达式

那如果拓展到一般情况该怎么办呢?

我们不难发现,对于一列公差为1的数,我们可以任意的对其分割周期

所以说我们的边界为2和3,那也就是下一次的周期应该是2*3=6

一般的

就会有6n,6n+1,6n+2,6n+3,6n+4,6n+5,6n+6(6n)

我们来看

6n,6n+2,6n+4,6n+6一定为偶数,所以不是素数

同样6n+3也一定是3的倍数

所以只剩下了6n+1和6n+5

想一个例外

6n+5可能是5的倍数怎么办?

没有事情的,在循环里去除就行了

或者说,在我们便利6n+1和6n+5时只需要额外的操作一下就可以了,例如2*3*4+1=25,但是25并不是素数

相似的,还有2*3*6-1=35,2*3*8+1=49

那么这些数满足什么式子呢?

不难发现,这几个数都是(6m±1)*(6n±1);的形式

所以在循环里只需要排除掉就可以了

好,不多说了(copyright@大连市第二十四中学地理姜亮老师)上代码:

#include<bits/stdc++.h>
using namespace std;
bool check(long long n)
{
    if (n == 1)
        return false;
    else 
	if (n == 2 || n == 3)
        return true;
    else 
	if (n % 6 != 1 && n % 6 != 5)
        return false;
    for(int i = 5;i <= sqrt(n);i += 6)
    {
        if (n % i == 0 || n % (i + 2) == 0)
            return false;
    }
    return true;
}
int main()
{
	long long min,max;
	long long sum = 0;
	cin >> min >> max;
	for(int i = min;i <= max;i ++)
	{
		if(check(i) == true)
		{
			cout << i << " ";
			sum ++;
		}
	}
	cout << sum;
	return 0;
}

时间复杂度

关于时间复杂度,(有两种观点)

基本同意了观点

I:

O(n*sqrt(n))

II:

O(n+sqrt(n))

应该是O(n^3/2)

以后测出具体的数值再更

在100000000时比欧拉筛慢1-2秒,但是结果符合,所以应该没有什么问题。

感谢OI的朋友们帮我测复杂度并指出了我的错误,的确是比欧拉筛要慢很多(20231216更新)

写在后面

请原谅我的狂妄

但是如果真的是在下第一个发现的

我想将其命名为:廿四筛

写在后面II

感谢:AClove,viki617,Qwehhh123,snowycat1234帮助我正确的测算时间复杂度并优化

李墨林 Merlin·Aquarius·Mark·Uranus·Lee

@大连市第二十四中学OIteam

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值