hdu 4099 Revenge of Fibonacci(字典树)

题目链接:hdu 4099 Revenge of Fibonacci

题目大意:给定一个前缀,找到最小的n,保证f(n)包含前缀。f为斐波那契数列,要求n小于100000。

解题思路:大数加法,对100000以内的斐波那契数预处理出前缀,这里处理的时候只需要对前50位进行加法处理即

可,否则复杂度过高,因为查询的长度不会超过40。然后建立字典树,查询则在字典树上进行搜索。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int maxn = 1e6 + 5;
const int sigma_size = 10;

struct Bign {
    int c, s[maxn];
    Bign() {}

    void operator = (int a) {
        c = 0;
        memset(s, 0, sizeof(s));
        while (a) {
            s[c++] = a % 10;
            a /= 10;
        }
    }

    void put() {
        for (int i = 1; i <= 40 && i <= c; i++)
            printf("%d", s[c-i]);
        printf("\n");
    }
}num[3];

void add(const Bign& a, const Bign& b, Bign& ans) {
    int tmp = 0;

    ans.c = max(a.c, b.c);
    for (int i = max(min(a.c, b.c) - 50, 0); i < a.c || i < b.c; i++) {
        if (i < a.c) tmp += a.s[i];
        if (i < b.c) tmp += b.s[i];
        ans.s[i] = tmp % 10;
        tmp /= 10;
    }

    while (tmp) {
        ans.s[ans.c++] = tmp % 10;
        tmp /= 10;
    }
}

struct Tire {
    int sz, g[maxn * 10][sigma_size];
    int val[maxn * 10];

    void init();
    int find(char* s);
    void insert(const Bign& a, int x);
}T;

void init () {
    num[0] = 1;
    num[1] = 1;

    T.init();
    T.insert(num[0], 1);
    T.insert(num[1], 2);

    int t = 2;
    for (int i = 2; i < 100000; i++) {
        add(num[(t+1)%3], num[(t+2)%3], num[t]);
        T.insert(num[t], i + 1);
        t = (t + 1) % 3;
    }
}

int main () {
    init();
    int cas;
    char s[60];;

    scanf("%d", &cas);
    for (int kcas = 1; kcas <= cas; kcas++) {
        scanf("%s", s);
        printf("Case #%d: %d\n", kcas, T.find(s) - 1);
    }
    return 0;
}

void Tire::init() {
    sz = 1;
    val[0] = 0;
    memset(g[0], 0, sizeof(g[0]));
}

int Tire::find(char* s) {
    int n = strlen(s), u = 0;
    for (int i = 0; i < n; i++) {
        int v = s[i] - '0';

        if (g[u][v] == 0)
            return 0;
        u = g[u][v];
    }
    return val[u];
}

void Tire::insert(const Bign& a, int x) {
    int u = 0;
    for (int i = 1; i <= 40 && i <= a.c; i++) {
        int v = a.s[a.c - i];

        if (g[u][v] == 0) {
            val[sz] = x;
            memset(g[sz], 0, sizeof(g[sz]));
            g[u][v] = sz++;
        }
        u = g[u][v];
    }
}

你可能感兴趣的:(hdu 4099 Revenge of Fibonacci(字典树))