import math def sieve_segment(n): if n < 2: return [] sieve = [True] * (n + 1) sieve[0] = sieve[1] = False for i in range(2, int(math.isqrt(n)) + 1): if sieve[i]: sieve[i*i : n+1 : i] = [False] * len(sieve[i*i : n+1 : i]) return [i for i, is_p in enumerate(sieve) if is_p] def segmented_sieve(n): if n < 2: return [] sqrt_n = int(math.isqrt(n)) small_primes = sieve_segment(sqrt_n) primes = [] segment_size = sqrt_n low = 2 while low <= n: high = min(low + segment_size - 1, n) sieve = [True] * (high - low + 1) for p in small_primes: start = max(p * p, ((low + p - 1) // p) * p) start -= low if start < 0: start += p for j in range(start, len(sieve), p): sieve[j] = False for i in range(len(sieve)): if sieve[i]: primes.append(low + i) low = high + 1 return primes L, R = map(int, input().split()) size = R - L + 1 is_square_free = [True] * size max_p = int(math.isqrt(R)) primes = segmented_sieve(max_p) for p in primes: s = p * p if s > R: continue first = ((L + s - 1) // s) * s if first > R: continue start_idx = first - L step = s for idx in range(start_idx, size, step): is_square_free[idx] = False print(sum(is_square_free))