Cod sursa(job #443923)

Utilizator SpiderManSimoiu Robert SpiderMan Data 18 aprilie 2010 21:28:35
Problema Numere 2 Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.45 kb
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cassert>

#define BASE 100000000
#define nbase 9
#define LUNG 30
#define PRTF "%04d"

inline void print(int *a)
{
       int t, p, i, j;
       printf ("%d\n" ,a[a[0]]);
       for (i = a[0] - 1; i ; --i)
       {
               t = 0; p = a[i];
               while ( p ) p /= 10, ++t;
               for (j = 1; j <= nbase - t; ++j) printf("0");
                if ( a[i] ) printf("%d", a[i]);
         }
}


void set(int *a, int value)
{
    memset(a, 0x00, sizeof(int)*LUNG);
    while (value)
    {
        a[++ a[0]] = value % BASE;
        value /= BASE;
    }
}

void mul(int *a, int scalar)
{
    int i, t = 0;

    for (i = 1; i <= a[0]; ++ i)
    {
        t += a[i]*scalar;
        a[i] = t % BASE;
        t /= BASE;
    }

    while (t)
    {
        a[i ++] = t % BASE;
        t /= BASE;
    }

    a[0] = i-1;
}

void div_2(int *a)
{
    int rest = 0;
    int i;

    for (i = a[0]; i > 0; -- i)
    {
        a[i] = rest*BASE+a[i];
        rest = a[i] % 2;
        a[i] /= 2;
    }

    while (a[a[0]] == 0 && a[0] > 0)
        a[0] --;
}

void add(int *a, int scalar)
{
    int i;

    for (i = 1; i <= a[0] && scalar != 0; ++ i)
    {
        scalar += a[i];
        a[i] = scalar % BASE;
        scalar /= BASE;
    }

    while (scalar)
    {
        a[i ++] = scalar % BASE;
        scalar /= BASE;
    }

    if (i > a[0])
        a[0] = i-1;
}

void dec(int *a)
{
    int i = 1;

    while (a[i] == 0)
        a[i ++] = BASE-1;
    a[i] --;

    if (i == a[0] && a[i] == 0)
        a[0] --;
}

int cmp(const int *a, const int *b)
{
    int i;

    if (a[0] != b[0])
        return a[0] - b[0];

    for (i = a[0]; i >= 1; -- i)
        if (a[i] != b[i])
            return a[i] - b[i];

    return 0;
}

void mul_(int *a, const int *b)
{
    int C[LUNG];
    int i;

    set(C, 0);

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

        t = 0;
        for (j = 1; j <= b[0]; ++ j)
        {
            t += C[i+j-1] + a[i]*b[j];
            C[i+j-1] = t % BASE;
            t /= BASE;
        }

        while (t != 0)
        {
            t += C[i+j-1];
            C[i+j-1] = t % BASE;
            t /= BASE;
        }
    }

    C[0] = LUNG-1;
    while (C[C[0]] == 0 && C[0] > 0)
        C[0] --;

    memcpy(a, C, sizeof(int)*LUNG);
    assert(a[0] < LUNG);
}

void add_(int *a, const int *b)
{
    int i, t = 0;
    for (i = 1; i <= a[0] || i <= b[0] || t != 0; ++ i)
    {
        t += a[i] + b[i];
        a[i] = t % BASE;
        t /= BASE;
    }

    if (i > a[0])
        a[0] = i - 1;
}

void power(const int *a, int b, int *c)
{
    int i;

    set(c, 1);
    for (i = 0; i < b; ++ i)
        mul_(c, a);
}


int P[LUNG];
int T[LUNG];
int B;

int main()
{
    int *left = (int*) malloc(sizeof(int)*LUNG);
    int *right = (int*) malloc(sizeof(int)*LUNG);
    int *mid = (int*) malloc(sizeof(int)*LUNG);
    char ch;


    freopen("numere2.in", "rt", stdin);
    freopen("numere2.out", "wt", stdout);

    set(P, 0);
    while (scanf(" %c", &ch) == 1)
    {
        mul(P, 10);
        add(P, (int)(ch - '0'));
    }

    set(T, 1);
    B = 0;
    while (cmp(T, P) < 0)
    {
        mul(T, 2);
        B ++;
    }

    if (cmp(T, P) == 0)
    {
        printf("%d\n%d\n", 2, B);
        return 0;
    }

    B --;
    while (B > 0)
    {
        set(left, 2);

        set(right, 1);
        do
        {
            mul(right, 2);
            power(right, B, T);
        }
        while (cmp(T, P) < 0);

        while (cmp(left, right) <= 0)
        {
            int res;

            memcpy(mid, left, sizeof(int)*LUNG);
            add_(mid, right);
            div_2(mid);

            power(mid, B, T);
            res = cmp(T, P);

            if (res == 0)
            {
                print(mid);
                printf("%d\n", B);
                return 0;
            }

            if (res < 0)
            {
                int *temp = left;
                left = mid;
                mid = temp;
                add(left, 1);
            }
            else
            {
                int *temp = right;
                right = mid;
                mid = temp;
                dec(right);
            }
        }

        B --;
    }


    return 0;
}