# import bitops # from strutils import toBin # type # Bit = distinct uint64 # BitIndex = (when defined(BitRange): BitRange else: range[0..63]) # template bitBinaryOperator(operatorName: untyped) = # proc `operatorName`*(a, b: Bit): Bit = Bit(`operatorName`(a.uint64, b.uint64)) # proc `operatorName`*(a: Bit; b: SomeUnsignedInt): Bit {.borrow.} # proc `operatorName`*(a: SomeUnsignedInt; b: Bit): Bit {.borrow.} # bitBinaryOperator(`and`) # bitBinaryOperator(`or`) # bitBinaryOperator(`xor`) # template bitShiftOperator(operatorName: untyped) = # proc `operatorName`*(a: Bit; b: SomeInteger): Bit = Bit(`operatorName`(a.uint64, b)) # bitShiftOperator(`shl`) # bitShiftOperator(`shr`) # bitShiftOperator(`ashl`) # bitShiftOperator(`ashr`) # template bitComparOperator(operatorName: untyped) = # proc `operatorName`*(a, b: Bit): bool = `operatorName`(a.uint64, b.uint64) # proc `operatorName`*(a: Bit; b: SomeUnsignedInt): bool {.borrow.} # proc `operatorName`*(a: SomeUnsignedInt; b: Bit): bool {.borrow.} # bitComparOperator(`==`) # proc isSetBit*(bits: Bit; i: BitIndex): bool {.inline.} = # ((bits shr i) and 1'u64) != 0'u64 # proc setBit*(bits: var Bit; i: BitIndex) {.inline.} = # bits = bits or (Bit(1) shl i) # proc unsetBit*(bits: var Bit; i: BitIndex) {.inline.} = # bits = bits and (not (Bit(1) shl i)) # when not defined(countSetBits): # proc countSetBits*(bits: Bit): int {.inline.} = # result = bits.int # result = ((result and 0x5555555555555555) + (result shr 1 and 0x5555555555555555)).int # result = ((result and 0x3333333333333333) + (result shr 2 and 0x3333333333333333)).int # result = ((result and 0x0f0f0f0f0f0f0f0f) + (result shr 4 and 0x0f0f0f0f0f0f0f0f)).int # result = ((result and 0x00ff00ff00ff00ff) + (result shr 8 and 0x00ff00ff00ff00ff)).int # result = ((result and 0x0000ffff0000ffff) + (result shr 16 and 0x0000ffff0000ffff)).int # result = ((result and 0x00000000ffffffff) + (result shr 32 and 0x00000000ffffffff)).int # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 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 let 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 + 1 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) - 1