Cod sursa(job #311572)

Utilizator DastasIonescu Vlad Dastas Data 3 mai 2009 18:23:44
Problema Numere 2 Scor 55
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.19 kb
#include <cstdio>
#include <cstring>

const int base = 10000;
const int nrcif = 100;

FILE *in = fopen("numere2.in","r"), *out = fopen("numere2.out","w");

struct bignum
{
    int nr[nrcif];

    bignum()
    {
        for ( int i = 0; i < nrcif; ++i )
            nr[i] = 0;
    }

    int &operator [](int x)
    {
        return nr[x];
    }
};

bignum p;
void read()
{
    char buf[nrcif*10];

    fscanf(in, "%s", buf);

    int i = strlen(buf) - 1;
    while ( i >= 0 )
    {
        int start = i - 4 + 1;
        if ( start < 0 )
            start = 0;

        ++p[0];
        for ( int j = start; j < start + 4 && buf[j]; ++j )
            p[ p[0] ] = 10 * p[ p[0] ] + (buf[j] - '0');

        i -= 4;
    }
}

void print(bignum &x)
{
    fprintf(out, "%d", x[ x[0] ]);
    for ( int i = x[0] - 1; i > 0; --i )
        fprintf(out, "%04d", x[i]);
    fprintf(out, "\n");
}

int compare(bignum &x, bignum &y)
{
    if ( x[0] > y[0] ) return 1; // x mai mare
    else if ( x[0] < y[0] ) return 2; // y mare mare

    for ( int i = x[0]; i > 0; --i )
        if ( x[i] > y[i] ) return 1;
        else if ( x[i] < y[i] ) return 2;

    return 3; // egale;
}

bignum add(bignum &x, bignum &y)
{
    bignum ret;

    int s = 0, c = 0;
    for ( int i = 1; i <= x[0] || i <= y[0] || c; ++i )
    {
        s = x[i] + y[i];

        ret[ ++ret[0] ] = (s + c) % base;

        c = s / base;
    }

    return ret;
}

void div2(bignum &x)
{
    int t = 0;

    for ( int i = x[0]; i > 0; --i )
    {
        t = base*t + x[i];

        x[i] = t / 2;
        t %= 2;
    }

    while ( !x[ x[0] ] && x[0] > 1 )
        --x[0];
}

bignum mult(bignum &x, bignum &y)
{
    bignum ret;

    ret[0] = x[0] + y[0] - 1;

    for ( int i = 1; i <= x[0]; ++i )
        for ( int j = 1; j <= y[0]; ++j )
            ret[i+j-1] += x[i] * y[j];

    int s = 0, t = 0;
    for ( int i = 1; i <= ret[0]; ++i )
    {
        s = ret[i] + t;

        ret[i] = s % base;

        t = s / base;
    }

    if ( t )
        ret[ ++ret[0] ] = t;

    return ret;
}

int main()
{
    read();

    bignum st, dr;
    bignum m, tmp;

    //print(p);
    bignum unu;
    unu[0] = 1, unu[1] = 1;
    for ( int i = 200; i; --i )
    {
        st[0] = 1;
        st[1] = 1;
        dr[0] = 30;
        dr[30] = 1;

        while ( compare(st, dr) == 2 )
        {
            m = add(st, dr);
            div2(m);

            int t = compare(m, p);
            if ( t == 1 )
            {
                dr = m;
                continue;
            }

            tmp = m;
            for ( int j = 1; j < i; ++j )
            {
                tmp = mult(tmp, m);
                if ( compare(tmp, p) == 1 )
                    break;
            }

            t = compare(tmp, p);
            if ( t == 1 ) // baza prea mare
                dr = m;
            else if ( t == 2 ) // baza prea mica
                st = add(m, unu);
            else // hopa
            {
                print(m);
                fprintf(out, "%d\n", i);
                return 0;
            }
        }
    }

    return 0;
}