Cod sursa(job #536259)

Utilizator vladiiIonescu Vlad vladii Data 18 februarie 2011 14:23:07
Problema Numere 2 Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.4 kb
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 32 * 2
#define BASE 10000

int N, NR[maxn];
int As[maxn], Bs;
int ls[maxn], ld[maxn], mij[maxn], aux[maxn], aux2[maxn], a[maxn], sol[maxn], unu[maxn];
char A[maxn];

void copy(int dest[], int sursa[]) {
    dest[0] = sursa[0];
    for(int i=1; i<=dest[0]; i++) {
         dest[i] = sursa[i];
    }
}

int cmp(int A[], int B[]) {
    if(A[0] > B[0]) return 1;
    if(A[0] < B[0]) return 2;

    for(int i=A[0]; i>=1; i--) {
         if(A[i] > B[i]) return 1;
         if(A[i] < B[i]) return 2;
    }

    return 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 add(int a[], 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 diff(int a[], int b[]) {
	int i;

	for (i = 1; i <= a[0] || i <= b[0]; i++) {
		a[i] -= b[i];
		if (a[i] < 0) a[i] += BASE, a[i + 1]--;
	}

	while (a[0] && !a[a[0]]) a[0]--;
}

void mul(int a[], int b[]) {
    int C[maxn];
    int i;

    memset(C, 0, sizeof(C));

    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] = maxn - 1;
    while(C[C[0]] == 0 && C[0] > 0)
        C[0] --;

    memcpy(a, C, sizeof(int)*maxn);
}

void mul(int a[], int B) {
    int i, t = 0;

    for(i = 1; i <= a[0]; ++ i) {
        t += a[i]*B;
        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] --;
}

int ridica_putere(int B) {
    memset(sol, 0, sizeof(sol));
    memset(a, 0, sizeof(a));
    copy(a, aux);

    sol[0] = 1, sol[1] = 1;
    for(int i=0; (1<<i)<=B; i++) {
         if (((1<<i) & B) > 0) {
              if(cmp(a, NR) == 1) return 1;
              mul(sol, a);
         }

         if(a[0] < maxn/2 - 1) {
              memset(aux2, 0, sizeof(aux2));
              copy(aux2, a);
              mul(aux2, a);
              memset(a, 0, sizeof(a));
              copy(a, aux2);
         }
         if(cmp(sol, NR) == 1) return 1;
    }

    return cmp(sol, NR);
}

int solve(int B) {
    int i, j, p, q;

    memset(ls, 0, sizeof(ls));
    memset(ld, 0, sizeof(ld));

    ls[0] = 1, ls[1] = 1;
    copy(ld, NR);

    while(cmp(ls, ld) != 1) {
         //for(i=ls[0]; i>=1; i--) {
         //     cout<<ls[i];
         //} cout<<" : ";
         //for(i=ld[0]; i>=1; i--) {
         //     cout<<ld[i];
         //} cout<<endl;

         memset(aux, 0, sizeof(aux));
         //aux = (ls + ld) / 2;
         copy(aux, ls);
         add(aux, ld);
         div_2(aux);

         int rez = ridica_putere(B);

         if(rez == 0) {
              memset(As, 0, sizeof(As));
              copy(As, aux);
              Bs = B;
              return 1;
         }
         else if(rez == 1) {
              //caut o valoare mai mica
              //ld = aux - 1;
              diff(aux, unu);
              memset(ld, 0, sizeof(ld));
              copy(ld, aux);
         }
         else {
              //caut o valoare mai mare
              //ls = aux + 1;
              add(aux, unu);
              memset(ls, 0, sizeof(ls));
              copy(ls, aux);
         }
    }

    return 0;
}

int main() {
    FILE *f1=fopen("numere2.in", "r"), *f2=fopen("numere2.out", "w");

    fscanf(f1, "%s\n", A+1);
    N = strlen(A+1);
    for(int i=1; i<=N; i++) {
         mul(NR, 10);
         add(NR, A[i] - '0');
    }

    unu[0] = 1, unu[1] = 1;

    for(int i=300; i>=1; i--) {
         if(solve(i)) break;
    }

    for(int i=As[0]; i>=1; i--) {
         fprintf(f2, "%d", As[i]);
    } fprintf(f2, "\n");
    fprintf(f2, "%d\n", Bs);

    fclose(f1); fclose(f2);
    return 0;
}