Cod sursa(job #444156)

Utilizator SpiderManSimoiu Robert SpiderMan Data 19 aprilie 2010 16:51:38
Problema Numere 2 Scor 85
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.3 kb
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cassert>

#define BASE 10000
#define LUNG 30
#define PRTF "%04d"


void print(int a[LUNG])
{
    int i = a[0];

    printf("%d", a[i]);

    while (-- i > 0)
        printf(PRTF, a[i]);
    printf("\n");
}

void atrh(int A[LUNG],int B[LUNG])
{
    for (int i = 0; i <= B[0]; ++i) A[i] = B[i];
}
void set(int A[LUNG], int X)
{
    memset(A, 0, sizeof(int)*LUNG);
    A[0] = 0;
    while (X)
    {
        ++A[0];
        A[A[0]] = X % BASE;
        X /= BASE;
    }
}

void mul(int A[LUNG], int B)
{
    int i, t = 0;
    for (i = 1; i <= A[0] || t; i++, t /= BASE)
        A[i] = (t += A[i] * B) % BASE;
    A[0] = i - 1;
}

void div_2(int a[LUNG])
{
    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;
    }

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

void add(int a[LUNG], int scalar)
{
    int i;

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

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

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

void dec(int a[LUNG])
{
    int i = 1;

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

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

inline int cmp(int A[LUNG], int B[LUNG])
{
    if (A[0] < B[0]) return -1;
    else if (A[0] > B[0]) return 1;
    for (int i = A[0]; i > 0; --i)
        if (A[i] < B[i]) return -1;
        else if (A[i] > B[i]) return 1;
    return 0;
}

void mul_(int A[LUNG], const int B[LUNG])
{
    int i, j, t, C[LUNG << 1];
    set(C,0);
    for (i = 1; i <= A[0]; i++)
    {
        for (t=0, j=1; j <= B[0] || t; j++, t/=BASE)
            C[i+j-1]=(t+=C[i+j-1]+A[i]*B[j])%BASE;
        if (i + j - 2 > C[0]) C[0] = i + j - 2;
    }
    memcpy(A, C, sizeof(int) * LUNG);
}

void add_(int A[LUNG], const int B[LUNG])
{
    int i, t = 0;
    for (i=1; i<=A[0] || i<=B[0] || t; i++, t/=BASE)
        A[i] = (t += A[i] + B[i]) % BASE;
    A[0] = i - 1;
}

void power(const int a[LUNG], int b, int c[LUNG])
{
    // c = a^b
    int i;

    set(c, 1);

    if (b == 0) return ;
    if (b % 2 == 0)
    {
        for (i = 0; i < b >> 1; ++i)
            mul_(c, a);
        mul_(c, c);
    }
    else
    {
        for (i = 0; i < b - 1 >> 1; ++i)
            mul_(c, a);
        mul_(c, c);
        mul_(c, a);
    }
}


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

int main()
{
    int left[LUNG] ;//= (int*) malloc(sizeof(int)*LUNG);
    int right[LUNG] ;//= (int*) malloc(sizeof(int)*LUNG);
    int mid[LUNG] ;//= (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;
                atrh(left,mid);//left = mid;
                atrh(mid,temp);//mid = temp;
                add(left, 1);
            }
            else
            {
                int *temp = right;
                atrh(right,mid);//right = mid;
                atrh(mid,temp);//mid = temp;
                dec(right);
            }
        }

        B --;
    }


    return 0;
}