想法来源于抖音刷到的一个小学规律题 33,34,35,( ),39中间填什么数?
通过规律我们可以看到每个元素都可以由两个素数相乘得到,中间填"38" 2*19=38
不难发现这样的半素数可以组成数列4,6,9,10....
如果找到第n项?通过这几天(期末考前)的研究,发现可以通过筛法解决这个问题(很不幸,通过查阅发现在2002年有人提出过了),在探究半素数问题时,知道了“陈素数”的概念,对于一个素数p,若p+2是素数或者是两个素数的乘积,则p称为陈素数(Chen prime),以中国数学家陈景润命名。致敬!
首先我们可以确定的是,这个数列的数肯定都是合数。我们先筛掉素数。
通过我灵敏的观察发现只有不是其他合数的倍数才是这个数列的数。(这也是筛法解决问题的根本)
如何验证这个猜想?
我的想法是。如果存在一个合数是其他合数的倍数,这样我们可以将这个合数分解成一个合数*一个质数,或者一个合数*一个合数。
在第一种情况中,如果我们想把其中的合数去掉,必然要去掉这个合数的某个因子,而这个因子如果加到另一个质数上,那么这个质数就会变成合数。
在第二种情况中,显然不符合条件。
而在我们从小到大筛的时候,最先遇到的合数肯定最小也就不是其他合数的倍数,这样我们可以把它选中,同时筛去他的倍数。
_______________________________________________________________
尽管如此,这个想法只能去验证是合数的倍数的数不算半素数,但依然无法很好的验证第一个合数就是半素数。因此,根据规律,我选择通过python做图表的方式来分析我的做法的数据是否和oeis的数据一致。
实现代码:
void shai1(){ sign[1] = false; for(int i = 2; i <= fn; i++) { if(!sign[i]) prime[++cnt] = i; for(int j = 1; j <= cnt && i * prime[j] <= fn; ++j) { sign[i * prime[j]] = true; if(i % prime[j] == 0) break; } } } void shai2(){ for(int i=4;i<=fn;i++){ if(sign[i]){ ve.push_back(i); for(int j=2;i*j<=fn;j++) sign[i*j] = false; } } }
前者提出的论文并没有找到,在找到提出这个线索前,通过python绘制图形和oeis的图形进行了对比,结果表明,数据不存在问题。
python代码:
import numpy as np import matplotlib.pyplot as plt import random x_data = [] y_data = [] sign = [] fn = 200 def shai1(): for i in range(2,1000000): if(sign[i]==False): j=2 while (i*j<1000000): sign[i*j] = True j=j+1 def shai2(): for i in range(2,1000000): if(sign[i]): y_data.append(i); if(len(y_data)>=fn): break j = 2; while(i*j<1000000): sign[i*j] = False j=j+1 def zhu(): # 准备数据 # 正确显示中文和负号 plt.rcParams["font.sans-serif"] = ["SimHei"] plt.rcParams["axes.unicode_minus"] = False # 画图,plt.bar()可以画柱状图 for i in range(len(x_data)): plt.bar( x_data[i],y_data[i]) # 设置图片名称 plt.title("数值分析") # 设置x轴标签名 plt.xlabel("第n项") # 设置y轴标签名 plt.ylabel("数值an") # 显示 plt.show() for i in range(1,fn): x_data.append(i) for i in range(1,1001000): sign.append(False) shai1() shai2() zhu()
python图片:
oeis图片: