aacord’s memo

abcを中心にpythonで解いた問題のメモ、整理をしています。緑になった。

abc 084 d

10**5までの素数のリストをどう作るのが早いかという話。
とりあえず python 素数判定 高速 でググってこれをコピペしてみた。ミラーテストというらしい。
Pythonを使って高速素数判定をしてみる - Pashango’s Blog
k = 13 のときで 1700ms だった。 4**13分の1で間違えるらしい。
次にエラトステネスの篩を使った。1413ms とちょっと早い。
色々考えて、とりあえずフェルマーテストして、そこから素数ではないけど弾かれない疑素数だけ強引に取り除いたらいいのではとなり、10万まで限定で高速に素数のリストを作る不器用なコードが完成した。483ms くらいまで早くなった。
一応説明すると、5と7でフェルマーテストして、素数だけど弾かれる 5,7 を先に入れて、弾かれない
561, 11041, 29341, 38081, 46657, 50737, 75361, 79381, 88831 を強引に引くという戦法

def is_prime(q):
    if q < 2 or q&1 == 0: return False
    return pow(5, q-1, q)*pow(7, q-1, q) == 1
  
def main():
  s = set([561, 11041, 29341, 38081, 46657, 50737, 75361, 79381, 88831])
  b = [2,5,7]
  for i in range(2,10**5):
    if i in s:
      continue
    if is_prime(i):
      b.append(i)

  a = set([2*i-1 for i in b])
  b = set(b)
  chk = sorted(tuple(a&b))

  from bisect import bisect,bisect_left
  import sys
  input = sys.stdin.readline

  q = int(input())
  for i in range(q):
    l,r = map(int,input().split())
    print(bisect(chk,r)-bisect_left(chk,l))
    
if __name__ == '__main__':
    main()