Cod sursa(job #2067256)

Utilizator alexpetrescuAlexandru Petrescu alexpetrescu Data 16 noiembrie 2017 03:12:37
Problema Numere 2 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.85 kb
#include <cstdio>
#include <cctype>
#include <cstring>

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

#define MAXK 209

int k[MAXK], aux[MAXK], a[MAXK];
int cat[MAXK], sol[MAXK], r[MAXK];
int ans[MAXK], pas[MAXK];

inline int cmp(int v[]) {
    int p = 0;
    if (v[0] == k[0]) {
        p = v[0];
        while (p > 1 && v[p] == k[p])
            p--;
    }
    if (v[p] > k[p]) return 1;
    else if (v[p] < k[p]) return -1;
    else return 0;
}

inline void inmult(int a[], int b[]) {
    memset(aux, 0, sizeof(int) * (aux[0] + 1));
    aux[0] = a[0] + b[0] - 1;
    for (int i = 1; i <= a[0]; i++)
        for (int j = 1; j <= b[0]; j++)
            aux[i + j - 1] += a[i] * b[j];
    int p = 1, tr = 0;
    while (p <= aux[0] || tr) {
        tr += aux[p];
        a[p] = tr % 10;
        tr /= 10;
        p++;
    }
    a[0] = p - 1;
}

inline void inmult(int a[], int x) {
    int i = 1, tr = 0;
    while (i <= a[0] || tr) {
        tr += a[i] * x;
        a[i] = tr % 10;
        tr /= 10;
        i++;
    }
    i--;
    if (i > a[0])
        a[0] = i;
}

inline void impart(int a[], int x) {
    int tr = 0;
    for (int i = a[0]; i > 0; i--) {
        int last = a[i];
        a[i] = (tr * 10 + a[i]) / x;
        tr = (tr * 10 + last) % x;
    }
    while (a[0] > 0 && a[a[0]] == 0)
        a[0]--;
}

inline void adun(int v[], int u[]) {
    int i = 1, tr = 0;
    while (i <= u[0] || tr) {
        tr += v[i] + u[i];
        v[i] = tr % 10;
        tr /= 10;
        i++;
    }
    i--;
    if (i > v[0])
        v[0] = i;
}

inline bool check(int v[], int n) {
    memset(cat, 0, sizeof(int) * (cat[0] + 1));
    cat[0] = cat[1] = 1;
    memset(sol, 0, sizeof(int) * (sol[0] + 1));
    memcpy(sol, v, sizeof(int) * (v[0] + 1));
    while (n && cmp(cat) <= 0) {
        if (n % 2) inmult(cat, sol);
        n /= 2;
        if (n) inmult(sol, sol);
    }
    return cmp(cat) <= 0;
}

inline bool egal(int n) {
    memset(cat, 0, sizeof(int) * (cat[0] + 1));
    cat[0] = cat[1] = 1;
    memset(sol, 0, sizeof(int) * (sol[0] + 1));
    memcpy(sol, a, sizeof(int) * (a[0] + 1));
    while (n && cmp(cat) <= 0) {
        if (n % 2) inmult(cat, sol);
        n /= 2;
        if (n) inmult(sol, sol);
    }
    return cmp(cat) == 0;
}

inline bool vezi(int b) {
    memset(a, 0, sizeof(int) * (a[0] + 1));
    memset(pas, 0, sizeof(int) * (pas[0] + 1));
    pas[0] = 1;
    pas[1] = 2;
    while (check(pas, b))
        inmult(pas, 2);
    impart(pas, 2);
    while (pas[0] > 0) {
        memset(r, 0, sizeof(int) * (r[0] + 1));
        memcpy(r, pas, sizeof(int) * (pas[0] + 1));
        adun(r, a);
        if (check(r, b)) {
            memset(a, 0, sizeof(int) * (a[0] + 1));
            memcpy(a, r, sizeof(int) * (r[0] + 1));
        }
        impart(pas, 2);
    }
    if (egal(b)) memcpy(ans, a, sizeof(int) * (a[0] + 1));
    else return 1;
    return 0;
}

int main() {
    char ch = fgetc(fin);
    while (isdigit(ch)) {
        k[++k[0]] = ch - '0';
        ch = fgetc(fin);
    }
    for (int i = 1, j = k[0]; i < j; i++, j--)
        k[i] ^= k[j] ^= k[i] ^= k[j];

    int dr = 3.5 * k[0] + 1, st = 3 * k[0] - 3;
    int rez = st;
    a[0] = 1;
    a[1] = 2;
    for (int pas = 1 << 8; pas; pas >>= 1)
        if (rez + pas <= dr && check(a, rez + pas))
            rez += pas;
    if (egal(rez)) fprintf(fout, "2\n%d\n", rez);
    else {
        int b = 2.2 * k[0] + 1;
        while (b >= 2 && vezi(b))
            b--;
        if (b == 1) {
            memset(ans, 0, sizeof(int) * (ans[0] + 1));
            memcpy(ans, k, sizeof(int) * (k[0] + 1));
        }
        for (int i = ans[0]; i; i--)
            fputc(ans[i] + '0', fout);
        fprintf(fout, "\n%d\n", b);
    }

    fclose(fin);
    fclose(fout);
    return 0;
}