Cod sursa(job #936701)

Utilizator UnforgivenMihai Catalin Botezatu Unforgiven Data 8 aprilie 2013 13:44:33
Problema Hashuri Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 4.66 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <time.h>
#include <cstdlib>


using namespace std;

/*------------------------------------------------------*/

// Clasa de Baza ->

template <class Temp>
class Hash_Base
{

    virtual void generate_random() = 0;

    virtual int hash_function1(Temp&) = 0;
    virtual int hash_function2(Temp&) = 0;

    virtual bool insert (Temp&) = 0;
    virtual bool erase (Temp&) = 0;
    virtual bool find (Temp&) = 0;

    virtual void operator *= (Temp&) = 0;
    virtual void operator /= (Temp&) = 0;
    virtual bool operator %= (Temp&) = 0;

    public:

    int a1,b1,a2,b2,prim;
    Temp * table1;
    Temp * table2;
    int hash_size;

    vector < pair <Temp,bool> > *operations;

};

/*--------------------------------------------------------*/

// Cuckoo Hash pentru Int32 ->

class Hash_Integer : public Hash_Base<int>
{

    int hash_function1(int&);
    int hash_function2(int&);

    void generate_random();

    public:
    bool insert(int&);
    bool erase(int&);
    bool find(int&);

    Hash_Integer(int size)
    {
        table1 = new int[size];
        table2 = new int[size];
        prim = 1000000009;
        operations = new vector < pair<int,bool> >;

        fill(table1 , table1 + size , 0);
        fill(table2 , table2 + size , 0);
        srand(time(NULL));
        hash_size = size;
        generate_random();
    }

    void operator *= (int&);
    void operator /= (int&);
    bool operator %= (int&);
};

void Hash_Integer::generate_random()
{
    a1 = rand() % hash_size;
    a2 = rand() % hash_size;
    b1 = rand() % hash_size;
    b2 = rand() % hash_size;
}

int Hash_Integer::hash_function1(int & value)
{
    return (((long long)a1 + (long long)value * (long long)b1 ) % (long long)prim) % (long long)hash_size;
}

int Hash_Integer::hash_function2(int & value)
{
    return (((long long)a2 + (long long)value * (long long)b2 ) % (long long)prim) % (long long)hash_size;
}

bool Hash_Integer::erase(int & value)
{
    int h1 = hash_function1(value);
    int h2 = hash_function2(value);

    if (table1[h1] == value)
    {
        table1[h1] = 0;
        return true;
    }

    if (table2[h2] == value)
    {
        table2[h2] = 0;
        return true;
    }

    return false;
}

bool Hash_Integer::find(int & value)
{
    int h1 = hash_function1(value);
    int h2 = hash_function2(value);

    if (table1[h1] == value)
    {
        return true;
    }

    if (table2[h2] == value)
    {
        return true;
    }

    return false;

}

bool Hash_Integer::insert(int & value)
{
    if (find(value)) return true;
    char which = 1;

    for (int i =0;i<30;i++)
    {
        int h1 = hash_function1(value);
        int h2 = hash_function2(value);
        if (table1[h1] == 0)
        {
            table1[h1] = value;
            return true;
        }
        else if(table2[h2] == 0)
        {
            table2[h2] = value;
            return true;
        }
        else
        {
            if (which == 1)
            {
                swap(value,table1[h1]);
            }
            else
            {
                swap(value,table2[h2]);
            }
            which = - which;
        }
    }
    return false;
}

void Hash_Integer::operator/= (int &value)
{
    if (erase(value))
    {
        operations -> push_back(make_pair(value,false));
    }
}

bool Hash_Integer::operator%= (int & value)
{
    return find(value);
}

void Hash_Integer::operator*=(int & value)
{
    operations -> push_back(make_pair(value,true));
    if (insert(value) == false)
    {
        generate_random();
        fill(table1 , table1 + hash_size , 0);
        fill(table2 , table2 + hash_size , 0);
        bool ok = false;
        while (ok == false)
        {
            ok = true;
            for (int i =0;i<operations -> size();i++)
            {
                bool op = (*operations)[i].second;
                int data = (*operations)[i].first;
                if (op)
                {
                    if (!insert(data))
                    {
                        ok = false;
                        break;
                    }
                }
                else
                {
                    erase(data);
                }
            }
        }
    }
}


int main()
{
    Hash_Integer *t = new Hash_Integer(1000000);
    ifstream input("hashuri.in");
    ofstream output("hashuri.out");
    int n;
    input >> n;
    for (int i =0;i<n;i++)
    {
        int op , x;
        input >> op >> x;
        if (op == 1)
        {
            *t *= x;
        }
        if (op == 2)
        {
            *t /= x;
        }
        if (op == 3)
        {
            output << (*t %= x) << "\n";
        }
    }
    return 0;
}