利用包含排斥原理求出给定范围内素数个数的问题

一.前提

今天上离散数学课上看到一个题目:使用包含排斥原理求不超过120的素数个数,其实按照一般算法是这样的:

count = 0
l = []
for x in range(121):
    #判断如果x是素数,则打印,如果不是素数就跳过
    if x <2:
        continue
    for i in range(2,x):
#如果能在2到该数的范围内找出一个数整除,就停止(相当于此数为合数),继续判断下一个数
        if x % i == 0:
            break
    else:
        l.append(x)
        count = count+1
print(l)
print(count)

这个方法就是一个一个判断,是毫不遗漏地找出全部素数,理解较简单。

而包含排斥原理解释如下图:

二.解题思路

今天讲的包含排斥原理求120以内素数个数,按照这个思维,我们只要找出120以内合数即可。11*11=121>120,可以推出120以内任意一个合数它的因子必定为{2,3,5,7}里的一个。

设集合Ai(i = 2,3,5,7)是120内能整除2,3,5,7这些数的集合。(手打太麻烦 嘿嘿(滑稽))

 

三.包含排斥法代码实现

N = 120
countA = int(N/2)  #|A| 能被2整除的数的个数
countB = int(N/3)  #|B| 能被3整除的数的个数
countC = int(N/5)  #|C| 能被5整除的数的个数
countD = int(N/7)  #|D| 能被7整除的数的个数

countAB = int(N / (2 * 3)); # | AB | 能同时被2,3整除的数的个数
countAC = int(N / (2 * 5)); # | AC | 能同时被2,5整除的数的个数
countAD = int(N / (2 * 7)); # | AD | 能同时被2,7整除的数的个数
countBC = int(N / (3 * 5)); # | AB | 能同时被3,5整除的数的个数
countBD = int(N / (3 * 7)); # | AB | 能同时被3,7整除的数的个数
countCD = int(N / (5 * 7)); # | AB | 能同时被5,7整除的数的个数


countABC =int( N / (2 * 3 * 5)); # | ABC | 能同时被2,3,5整除的数的个数
countABD = int(N / (2 * 3 * 7)); # | ABD | 能同时被2,3,7整除的数的个数
countACD = int(N / (2 * 5 * 7)); # | ABD | 能同时被2,5,7整除的数的个数
countBCD = int(N / (3 * 5 * 7)); # | ABD | 能同时被3,5,7整除的数的个数
countABCD =int(N / (2 * 3 * 5 * 7)); # | ABCD | 能同时被2,3,5,7整除的数的个数

#包含排斥原理
S = int(N - (countA + countB + countC + countD)
+ (countAB + countAC + countAD + countBC + countBD + countCD)
- (countABC + countABD + countACD + countBCD)
+ countABCD)+4-1
# 加4是原来的2,3,5,7这四个数也是质数,减1是1既不是质数也不是合数
print(S)

#属于估值法,适用于N不是特别大的情况,当N足够大时,素因子集合过大,本算法运算起来将会复杂。

四.改正

经过网友指正改正了答案,最后公式求出来的是~(A2∪A3∪A5∪A7),即除去这四个集合的部分。但通过韦恩图可以看出,2,3,5,7本身也是质数,1既不是质数也不是合数,所以最后结果是27+4-1=30个。

主要是做题太拘泥于公式,没有理解到精髓是通过韦恩图来检查结果。

很高兴回答你的问题。根据容斥原理,如果我们知道不超过2、3、5、7、11、13、17、19、23、29、31、37、41、43、47的素数个数,那么可以得到不超过48的素数个数。 首先是不超过2的素数个数,只有一个2,因此为1。 然后是不超过3的素数个数,有2和3,因此为2。 接着是不超过5的素数个数,有2、3和5,因此为3。 继续是不超过7的素数个数,有2、3、5和7,因此为4。 然后是不超过11的素数个数,有2、3、5、7和11,因此为5。 接下来是不超过13的素数个数,有2、3、5、7、11和13,因此为6。 继续是不超过17的素数个数,有2、3、5、7、11、13和17,因此为7。 然后是不超过19的素数个数,有2、3、5、7、11、13、17和19,因此为8。 接着是不超过23的素数个数,有2、3、5、7、11、13、17、19和23,因此为9。 继续是不超过29的素数个数,有2、3、5、7、11、13、17、19、23和29,因此为10。 然后是不超过31的素数个数,有2、3、5、7、11、13、17、19、23、29和31,因此为11。 接下来是不超过37的素数个数,有2、3、5、7、11、13、17、19、23、29、31和37,因此为12。 继续是不超过41的素数个数,有2、3、5、7、11、13、17、19、23、29、31、37和41,因此为13。 然后是不超过43的素数个数,有2、3、5、7、11、13、17、19、23、29、31、37、41和43,因此为14。 接着是不超过47的素数个数,有2、3、5、7、11、13、17、19、23、29、31、37、41、43和47,因此为15。 因此,根据容斥原理,不超过48的素数个数为: 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 - (素数个数超过2的交素数个数超过3的) - (素数个数超过2的交素数个数超过5的) - (素数个数超过2的交素数个数超过7的) - (素数个数超过2的交素数个数超过11的) - (素数个数超过2的交素数个数超过13的) - (素数个数超过2的交素数个数超过17的) - (素数个数超过2的交素数个数超过19的) - (素数个数超过2的交素数个数超过23的) - (素数个数超过2的交素数个数超过29的) - (素数个数超过2的交素数个数超过31的) - (素数个数超过2的交素数个数超过37的) - (素数个数超过2的交素数个数超过41的) - (素数个数超过2的交素数个数超过43的) - (素数个数超过2的交素数个数超过47的) = 15 因此,不超过48的素数个数为15个。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值