Cod sursa(job #2057793)

Utilizator SburlyAndrei Florin Sburly Data 4 noiembrie 2017 19:21:38
Problema Nunta Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 7.7 kb
#include <fstream>
#include <cassert>
#include <cstring>

using namespace std;

#define BUFF_SIZE 1002

class largeInt{
public:
    struct digit{
        short int a;
        digit* next;
        digit* prev;


        digit(short int dec)
        {
            a = dec;
            next = NULL;
            prev = NULL;
        }
    };

    largeInt(int n = 0)
    {
        if(n == 0)
        {
            first = new digit(0);
            last = first;
        }
        else
        {
            first = NULL;
            last = NULL;

            while(n)
            {
                digit* tmp = new digit(n%10);
                n = n/10;

                if(last)
                {
                    first->prev = tmp;
                    tmp->next = first;
                    first = tmp;
                }
                else
                {
                    last = tmp;
                    first = tmp;
                }
            }
        }
    }

    largeInt(digit* f, digit* l)
    {
        first = f;
        last = l;
    }

    largeInt(const largeInt& other)
    {
        for(digit* i = other.getFirst(); i != NULL; i=i->next)
        {
            digit* tmp = new digit(i->a);
            if(first)
            {
                last->next = tmp;
                tmp->prev = last;
                last = tmp;
            }
            else
            {
                first = tmp;
                last = tmp;
            }
        }
    }

    inline int size() const
    {
        return length;
    }

    inline digit* getFirst() const
    {
        return first;
    }

    inline digit* getLast() const
    {
        return last;
    }

    inline static short int dVal(const digit* dg)
    {
        if(dg)
            return dg->a;
        return 0;
    }

    void operator =(const largeInt& other)
    {
        digit* tmp = first;
        bool b = true;
        for(digit* i = other.getFirst(); i != NULL; i=i->next)
        {
            if(tmp)
            {
                tmp->a = i->a;
                tmp = tmp->next;
            }
            else
            {
                b = false;
                tmp = new digit(i->a);
                last->next = tmp;
                tmp->prev = last;
                last = tmp;
                tmp = NULL;
            }
        }
        if(b && tmp)
        {
            digit* i;
            do{
                i = tmp;
                tmp = tmp->next;
                delete i;
            }while(tmp);
        }
    }

    largeInt operator + (const largeInt& other)
    {
        digit* i = last;
        digit* j = other.getLast();
        digit* r_first = NULL;
        digit* r_last = NULL;

        int carry = 0;
        while(i || j)
        {
            short int rez = dVal(i) + dVal(j) + carry;
            carry = rez/10;
            rez-=carry*10;

            digit* tmp = new digit(rez);

            if(r_last)
            {
                tmp->next = r_first;
                r_first->prev = tmp;
                r_first = tmp;
            }
            else
            {
                r_first = tmp;
                r_last = tmp;
            }

            if(i)
                i = i->prev;
            if(j)
                j = j->prev;
        }
        if(carry)
        {
            digit* tmp = new digit(carry);
            tmp->next = r_first;
            r_first->prev = tmp;
            r_first = tmp;;
        }
        return largeInt(r_first, r_last);
    }

    largeInt operator - (const largeInt& other)
    {
        digit* i = last;
        digit* j = other.getLast();
        digit* r_first = NULL;
        digit* r_last = NULL;

        int carry = 0;
        while(i || j)
        {
            short int rez = dVal(i) - dVal(j) - carry;
            if(rez < 0)
            {
                carry = 1;
                rez+=10;
            }
            else
                carry = 0;

            digit* tmp = new digit(rez);

            if(r_last)
            {
                tmp->next = r_first;
                r_first->prev = tmp;
                r_first = tmp;
            }
            else
            {
                r_first = tmp;
                r_last = tmp;
            }

            if(i)
                i = i->prev;
            if(j)
                j = j->prev;
        }

        while(r_first->a == 0 && r_first!=r_last)
        {
            digit* tmp = r_first;
            r_first = r_first->next;
            delete tmp;
        }

        return largeInt(r_first, r_last);
    }

    largeInt operator * (const short int& cif)
    {
        assert(0<=cif && cif <= 9);

        digit* i = last;
        digit* r_first = NULL;
        digit* r_last = NULL;

        int carry = 0;
        while(i)
        {
            short int rez = dVal(i)*cif + carry;
            carry = rez/10;
            rez-=carry*10;

            digit* tmp = new digit(rez);

            if(r_last)
            {
                tmp->next = r_first;
                r_first->prev = tmp;
                r_first = tmp;
            }
            else
            {
                r_first = tmp;
                r_last = tmp;
            }

            if(i)
                i = i->prev;
        }
        if(carry)
        {
            digit* tmp = new digit(carry);
            tmp->next = r_first;
            r_first->prev = tmp;
            r_first = tmp;;
        }
        return largeInt(r_first, r_last);
    }

    largeInt operator * (const largeInt& other)
    {
        largeInt rez;
        int step;
        digit* j;
        for(j = other.getLast(), step = 0; j != NULL; j=j->prev, step++)
        {
            largeInt t = (*this) * (j->a);
            for(int i = 0; i < step; i++)
            {
                digit* tmp = new digit(0);
                t.last->next = tmp;
                tmp->prev = t.last;
                t.last = tmp;
            }
            rez = rez+t;
        }
        return rez;
    }

    static void print(const largeInt& a, ostream& g)
    {
        for(digit* i = a.getFirst(); i != NULL; i = i->next)
            g << i->a;
    }

    static void read(largeInt& a, istream& f, char sep)
    {
        char s[BUFF_SIZE];
        f.get(s,BUFF_SIZE,sep);
        const unsigned int n = strlen(s);

        a.~largeInt();
        a.first = NULL;
        a.last = NULL;

        for(unsigned int i = 0; i < n; i++)
        {
            digit* tmp = new digit(s[i]-'0');

            if(a.first)
            {
                a.last->next = tmp;
                tmp->prev = a.last;
                a.last = tmp;
            }
            else
            {
                a.first = tmp;
                a.last = tmp;
            }
        }
    }

    ~largeInt()
    {
        if(first)
        {
            digit* i;
            do{
                i = first;
                first = first->next;
                delete i;
            }while(first);
        }
        first = NULL;
        last = NULL;
    }
private:
    int length;
    digit* first;
    digit* last;

};

int n;

int main()
{
    ifstream f("nunta.in");
    ofstream g("nunta.out");

    f >> n;

    if(n == 1)
    {
        g << 1;
        return 0;
    }
    if(n == 2)
    {
        g << 2;
        return 0;
    }


    largeInt a(1);
    largeInt b(2);
    largeInt c(0);

    for(int i = 2; i < n; i++)
    {
        c = a+b;
        a = b;
        b = c;
    }

    largeInt::print(c,g);

    return 0;
}