本文章为原创文章,未经过允许不得转载
运行要求
运行时间限制: 2sec
内存限制: 1024MB
未经允许,不得许转载
原题链接

题目
如果有一个奇数N,N和(N+1//2)都是素数的话,N为2017的相似数
现在给定Q次查询
第i(1<=i<=Q)次查询,第i次查询给定奇数li,ri,求li<=x<=ri范围内,2017相似数的x的个数

输入前提条件

  • 1<=Q<=100000
  • 1<=li<=ri<=100000
  • li,ri为奇数
  • 所有的输入都为整数

输入
输入按照以下形式标准输入

Q
l1 r1
l2 r1
.
.
.
lQ rQ

输出
第i行输出,第i次查询的结果


例1
输入

1
3 7

输出

2

3和((3+1)/2)都为素数,所以3为2017的相似数
5和((5+1)/2)都为素数,所以5为2017的相似数
7虽然是素数,但是5((7+1)/2)不是素数,所以7不是2017的相似数
以上所述,查询1的结果为2

例2
输入

4
13 13
7 11
7 11
2017 2017

输出

1
0
0
1

注意2017也是2017的相似数

例2
输入

6
1 53
13 91
37 55
19 51
73 91
13 49

输出

4
4
1
1
1
2

读懂题目
给定一个区间,在这个区间的所有素数当中,挑选出折半以后仍然是素数的数字

解题思路
首先我们要看到li,ri的最大值是100000,最小值是1
li,ri决定了区间的左边界和右边界
所以区间的最大跨度是1到100000

首先我们要找到这个区间里面的所有的素数
因为是代码竞技所以不能使用第三方的扩展包
我们手写素数生成器
具体的方法用到素数筛选法
英文叫sieve of Eratosthenes

名称未設定.001.jpeg
我们取一串区间,记住最少要从2开始。我们找出这串数字的最小的元素,这里为2
先找出2的倍数,然后去掉它们

名称未設定.002.jpeg
在从剩下的里面找第1个没有被遍历的元素,这里是3
找出3的倍数,然后去掉它们

名称未設定.003.jpeg
依此类推,找出5的倍数,去掉他们

名称未設定.004.jpeg
有的时候,最小元素的倍数不存在了,那么什么都不用做

名称未設定.005.jpeg
以这种方式可以找到所有的素数

但是有一点要注意的是,遍历结束的标志。
区间从2到区间末尾
start可以从区间的开头遍历到区间的结尾,但是如果区间很大的话,我们只需要遍历到区间的平方根的地方就好了
比如2-16的话
我们只需要遍历到2-4
2-100的话
我们只需要遍历到2-10

好,我们拿到了1-100000的所有的素数

我们再次遍历一次1-100000,判断每一个数是不是2017的相似数
用累积和的求法,算出从1到遍历点i的相似数的个数

具体就是

**如果i为2017的相似数,那么
1到i的2017相似数的个数 = 1到(i-1)的2017相似数的个数 + 1**

**如果i不是2017的相似数,那么
1到i的2017相似数的个数 = 1到(i-1)的2017相似数的个数**

**最后对于区间(li,ri)内2017相似数的个数的统计=
1到ri的2017相似数的个数 - 1到(li-1)的2017相似数的个数**

代码

import math


def sushu(n):
    arr = []
    for i in range(2, n + 1):
        arr.append(i)

    limit = int(math.sqrt(n)) + 1

    prev = []
    while True:
        start = arr[0]
        prev.append(start)
        if start > limit:
            break
        brr = []
        for i in arr:
            if i % start != 0:
                brr.append(i)
        arr = brr

    prev.extend(arr)
    return prev


n = 100000
shushu = sushu(100000)

marks = []
for i in range(n + 1):
    marks.append(False)

for j in shushu:
    marks[j] = True

marks2 = []
result = []
for i in range(n + 1):
    if i % 2 == 0:
        marks2.append(False)
        if i == 0:
            result.append(0)
        else:
            result.append(result[i - 1])
    else:
        if marks[(i + 1) // 2] and marks[i]:
            marks2.append(True)
            result.append(result[i - 1] + 1)
        else:
            marks2.append(False)
            result.append(result[i - 1])

Q = int(input())

ARR = []

for i in range(Q):
    ARR.append(list(map(int, input().split())))

for i in range(Q):
    start = ARR[i][0]
    end = ARR[i][1]
    print(result[end] - result[start - 1])

总结
这道题考察了对素数的求法。运用素数筛选法可以求出某一个区间以内的所有的素数

另外考察了累积和的运用

※ 另外,我会在我的微信个人订阅号上推出一些文章,欢迎关注
二维码.jpg



伟大不DIAO
1 声望1 粉丝

Done is better than perfect