#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# c.durr + f.magniez- 2014

from math   import *
from random import *
from sys    import *

# number of distinct elements

class DistinctElementsNaive:
    def __init__(self):
        self.seen = set()

    def update(self, token):
        if token not in self.seen:
            self.seen.add(token)

    def val(self):
        return len(self.seen)

# create a flow of IP addresses

linenb  = 0
def stream_ip(filename):
    global linenb
    with open(filename) as fp:
        for line in fp:
            yield line.split()[0]

# streaming algorithme F1 estimator (Moris 1978)

def avr(L): return sum(L)/float(len(L))

class Count:
    def __init__(self):
        self.a = 0

    def incr(self):
        if randrange(0, 1<<self.a)==0:
            self.a += 1
    def val(self):
        return (1<<self.a)-1

class Estimator:
    def __init__(self, delta, epsilon):
        E = int(ceil(2/epsilon/epsilon   ))
        D = int(ceil(log(8/delta)/log(2) ))
        self.T = [[Count() for i in range(E)] for j in range(D)]

    def incr(self):
        for row in self.T:
            for c in row:
                c.incr()

    def val(self):
        A = [avr([c.val() for c in row]) for row in self.T]
        A.sort()
        n = len(A)
        if n%2==1:
            return A[(n-1)/2]
        else:
            return (A[n/2] + A[n/2+1] )/2.

class F1Moris:
    def __init__(self):
        self.c = Estimator(1e-4, 0.01)

    def update(self, token):
        self.c.incr()

    def val(self):
        return self.val()


if __name__=="__main__":
    A = DistinctElementsNaive()
    for ip in stream_ip(argv[1]):
        A.update(ip)
    print (A.val())