import java.util.*;
import java.util.concurrent.*;

public class Euler229 {

    static long isqrt(long n) {
        if (n == 0)
            return 0;
        long x = (long) Math.sqrt(n);
        while ((x + 1) * (x + 1) <= n)
            x++;
        while (x * x > n)
            x--;
        return x;
    }

    static int[] getBasePrimes(int n) {
        if (n < 2)
            return new int[0];
        byte[] isPrime = new byte[n + 1];
        Arrays.fill(isPrime, (byte) 1);
        isPrime[0] = isPrime[1] = 0;
        int root = (int) isqrt(n);
        for (int p = 2; p <= root; ++p) {
            if (isPrime[p] == 1) {
                for (int x = p * p; x <= n; x += p)
                    isPrime[x] = 0;
            }
        }
        int count = 0;
        for (int p = 2; p <= n; ++p)
            if (isPrime[p] == 1)
                count++;
        int[] primes = new int[count];
        int idx = 0;
        for (int p = 2; p <= n; ++p)
            if (isPrime[p] == 1)
                primes[idx++] = p;
        return primes;
    }

    static boolean isGoodPrime(long p) {
        if (p <= 7)
            return false;
        long residue = p % 168;
        return residue == 1 || residue == 25 || residue == 121;
    }

    static long singletonSumInRange(long low, long high, long limit, int[] basePrimes) {
        if (low > high || high < 2)
            return 0;
        int segmentSize = 1 << 20;
        long total = 0;

        for (long segmentLow = low; segmentLow <= high;) {
            long segmentHigh = Math.min(segmentLow + segmentSize - 1, high);
            int length = (int) (segmentHigh - segmentLow + 1);
            byte[] isPrime = new byte[length];
            Arrays.fill(isPrime, (byte) 1);

            for (int p : basePrimes) {
                long p2 = (long) p * p;
                if (p2 > segmentHigh)
                    break;
                long start = (segmentLow + p - 1) / p * p;
                if (start < p2)
                    start = p2;
                for (long x = start; x <= segmentHigh; x += p) {
                    isPrime[(int) (x - segmentLow)] = 0;
                }
            }

            if (segmentLow == 0) {
                isPrime[0] = 0;
                if (length > 1)
                    isPrime[1] = 0;
            } else if (segmentLow == 1) {
                isPrime[0] = 0;
            }

            for (long val = Math.max(2L, segmentLow); val <= segmentHigh; ++val) {
                if (isPrime[(int) (val - segmentLow)] == 1 && isGoodPrime(val)) {
                    total += isqrt(limit / val);
                }
            }
            segmentLow = segmentHigh + 1;
        }
        return total;
    }

    static long sumSingletonKernels(long limit, int threads) {
        if (limit < 11)
            return 0;
        int baseBound = (int) isqrt(limit);
        int[] basePrimes = getBasePrimes(baseBound);

        long last = limit;
        long count = last - 1;
        int workerCount = Math.min(threads, (int) Math.min(count, Integer.MAX_VALUE));
        long block = (count + workerCount - 1) / workerCount;

        ExecutorService executor = Executors.newFixedThreadPool(workerCount);
        List<Future<Long>> futures = new ArrayList<>();

        for (int tid = 0; tid < workerCount; ++tid) {
            final long low = 2 + tid * block;
            if (low > last)
                break;
            final long high = Math.min(last, low + block - 1);
            futures.add(executor.submit(() -> singletonSumInRange(low, high, limit, basePrimes)));
        }

        long total = 0;
        for (Future<Long> f : futures) {
            try {
                total += f.get();
            } catch (Exception e) {
            }
        }
        executor.shutdown();
        return total;
    }

    static long sumMultiPrimeKernelsDfs(int[] goodPrimes, long limit, int startIndex, long currentProduct,
            int pickedCount) {
        long total = 0;
        for (int i = startIndex; i < goodPrimes.length; ++i) {
            long p = goodPrimes[i];
            if (currentProduct > limit / p)
                break;
            long nextProduct = currentProduct * p;
            int nextPicked = pickedCount + 1;
            if (nextPicked >= 2) {
                total += isqrt(limit / nextProduct);
            }
            total += sumMultiPrimeKernelsDfs(goodPrimes, limit, i + 1, nextProduct, nextPicked);
        }
        return total;
    }

    static long sumMultiPrimeKernels(long limit) {
        if (limit < 193L * 193L)
            return 0;
        int maxFactor = (int) (limit / 193);
        int[] basePrimes = getBasePrimes(maxFactor);

        int cnt = 0;
        for (int p : basePrimes)
            if (isGoodPrime(p))
                cnt++;
        int[] goodPrimes = new int[cnt];
        int idx = 0;
        for (int p : basePrimes)
            if (isGoodPrime(p))
                goodPrimes[idx++] = p;

        return sumMultiPrimeKernelsDfs(goodPrimes, limit, 0, 1L, 0);
    }

    static int[] buildSpfTable(int n) {
        int[] spf = new int[n + 1];
        for (int i = 0; i <= n; ++i)
            spf[i] = i;
        int root = (int) isqrt(n);
        for (int i = 2; i <= root; ++i) {
            if (spf[i] == i) {
                for (int x = i * i; x <= n; x += i) {
                    if (spf[x] == x)
                        spf[x] = i;
                }
            }
        }
        return spf;
    }

    static class Factor {
        int p, e;

        Factor(int p, int e) {
            this.p = p;
            this.e = e;
        }
    }

    static List<Factor> factorizeDy2(int y, int d, int[] spf) {
        List<Factor> factors = new ArrayList<>();
        int val = y;
        while (val > 1) {
            int p = spf[val];
            int count = 0;
            while (val % p == 0) {
                val /= p;
                count++;
            }
            factors.add(new Factor(p, 2 * count));
        }

        int remD = d;
        for (int p = 2; p * p <= remD; ++p) {
            if (remD % p == 0) {
                int count = 0;
                while (remD % p == 0) {
                    remD /= p;
                    count++;
                }
                factors.add(new Factor(p, count));
            }
        }
        if (remD > 1)
            factors.add(new Factor(remD, 1));

        factors.sort((a, b) -> Integer.compare(a.p, b.p));
        List<Factor> merged = new ArrayList<>();
        for (Factor f : factors) {
            if (!merged.isEmpty() && merged.get(merged.size() - 1).p == f.p) {
                merged.get(merged.size() - 1).e += f.e;
            } else {
                merged.add(new Factor(f.p, f.e));
            }
        }
        return merged;
    }

    static void buildDivisorsRecursive(List<Factor> factors, int index, long current, List<Long> out) {
        if (index == factors.size()) {
            out.add(current);
            return;
        }
        long val = current;
        int p = factors.get(index).p;
        int e = factors.get(index).e;
        for (int i = 0; i <= e; ++i) {
            buildDivisorsRecursive(factors, index + 1, val, out);
            val *= p;
        }
    }

    static byte[] squareRootsWithPositiveRep(long limit, int d, int[] spf) {
        int maxRoot = (int) isqrt(limit);
        int maxY = (int) isqrt(limit / d);
        byte[] mark = new byte[maxRoot + 1];

        for (int y = 1; y <= maxY; ++y) {
            long D = (long) d * y * y;
            List<Factor> factors = factorizeDy2(y, d, spf);
            List<Long> divs = new ArrayList<>();
            buildDivisorsRecursive(factors, 0, 1L, divs);

            for (long u : divs) {
                long v = D / u;
                if (u > v)
                    continue;
                if (((u + v) & 1) != 0)
                    continue;
                if (v <= u)
                    continue;

                long m = (u + v) / 2;
                if (m <= maxRoot) {
                    mark[(int) m] = 1;
                }
            }
        }
        return mark;
    }

    static long countGoodSquares(long limit) {
        int maxRoot = (int) isqrt(limit);
        int[] spf = buildSpfTable(maxRoot);

        byte[] d1 = squareRootsWithPositiveRep(limit, 1, spf);
        byte[] d2 = squareRootsWithPositiveRep(limit, 2, spf);
        byte[] d3 = squareRootsWithPositiveRep(limit, 3, spf);
        byte[] d7 = squareRootsWithPositiveRep(limit, 7, spf);

        long count = 0;
        for (int m = 1; m <= maxRoot; ++m) {
            if (d1[m] == 1 && d2[m] == 1 && d3[m] == 1 && d7[m] == 1) {
                count++;
            }
        }
        return count;
    }

    public static String solve() {
        long limit = 2000000000L;
        int threads = Math.max(1, Runtime.getRuntime().availableProcessors());

        long sqKernel = isqrt(limit);
        long singleCont = sumSingletonKernels(limit, threads);
        long multiCont = sumMultiPrimeKernels(limit);

        long intRep = sqKernel + singleCont + multiCont;
        long totalSq = isqrt(limit);
        long goodSq = countGoodSquares(limit);

        return String.valueOf(intRep - totalSq + goodSq);
    }

    public static void main(String[] args) {
        System.out.println(solve());
    }
}
