from sequtils import newSeqWith, mapIt proc isSetBit*(bits: uint64, index: range[0..63]): bool {.inline.} = return ((bits shr index) and 1) != 0 proc unsetBit*(bits: var uint64; i: range[0..63]) {.inline.} = bits = bits and (not (1'u64 shl i)) proc isPrime(s: seq[uint64]; p: int): bool = s[p div 64].isSetBit(p mod 64) const maxN = 1_000_000 √maxN = 1_000 L = (maxN + 1 + 64 - 1) div 64 proc sieve*(): seq[uint64] = result = newSeqWith(L, not 0'u64) for i in 2..√maxN: if result.isPrime(i): for j in countup(i * i, maxN, i): result[j div 64].unsetBit(j mod 64) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # from strutils import split, parseInt, toBin from bitops import popcount const s = sieve() var N, P: int (N, P) = stdin.readLine.split.mapIt(it.parseInt) proc maskLeft(x: uint64; i: int): uint64 = ## x の i ビット目未満を 0 にする if i >= 64: x else: x and (not ((1'u64 shl i) - 1)) proc maskRight(x: uint64; i: int): uint64 = ## x の i ビット目より上を 0 にする if i < 0: 0'u64 else: x and ((1'u64 shl (i + 1)) - 1) proc f(s: seq[uint64]; N: int): int = let l = N div 2 r = N l64 = l div 64 r64 = r div 64 if l64 == r64: result = s[l64].maskLeft(l).maskRight(r).popcount else: result = s[l64].maskLeft(l).popcount for i in (l64 + 1)..(r64 - 1): result += s[i].popcount result += s[r64].maskRight(r).popcount # echo s[l64..r64].mapIt(it.BiggestInt.toBin(64)), " | ", N, " | ", result, " | ", [l, r], " | ", [l64, r64] # echo s[l64].maskLeft(l).BiggestInt.toBin(64) # echo s[r64].maskRight(r).BiggestInt.toBin(64) # echo s[l64].maskLeft(l).maskRight(r).BiggestInt.toBin(64) if (P <= 1 or P > N div 2) and s.isPrime(P): echo "1" else: echo N - f(s, N)