Cod sursa(job #337395)

Utilizator GheorgheMihaiMihai Gheorghe GheorgheMihai Data 3 august 2009 15:36:58
Problema Numere 2 Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.82 kb
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

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

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

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

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

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(void)
{
    int *left = malloc(sizeof(int)*LUNG);
    int *right = malloc(sizeof(int)*LUNG);
    int *mid = malloc(sizeof(int)*LUNG);
    char ch;

    freopen("numere.in", "rt", stdin);
    freopen("numere.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;
}