UVA12333--Revenge of Fibonacci

题意:
给你一个数字串,判断他是哪一个Fib数的前缀,有多种答案输出最小的,不存在输出-1。

思路:
大数加法计算斐波那契数,字典树搜索
计算过程中进行字典树的创建,计算时,当斐波那契数大于50位时,只计算高50位即可。

代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define maxn 100100
using namespace std;
typedef struct Node {
    int value;
    Node* next[10];
    Node() {
        value = -1;
        for (int i = 0; i < 10; i++)
            next[i] = NULL;
    }
} Node, *Tree;

int num[2][maxn];
Tree head;

void addNode(int *s, int len, int n) {
    Node* p = head;
    for (int i = 0; i < len; i++) {
        int x = s[i];
        if (p->next[x] == NULL)
            p->next[x] = new Node;
        p = p->next[x];
        if (p->value == -1)
            p->value = n;
    }
}

//计算斐波那契额数并创建字典树
void getFibAndTree() {
    head = new Node;
    head->next[1] = new Node;
    head->next[1]->value = 0;
    memset(num, 0, sizeof(num));
    num[0][0] = num[1][0] = 1;
    int b = 0, e = 1, flag = 0;
    for (int i = 2; i < 100000; i++) {
        int jw = 0;
        for (int j = b; j < e; j++) {
            int t = num[0][j] + num[1][j] + jw;
            jw = 0;
            if (t > 9)
                jw = 1;
            num[flag][j] = t % 10;
        }
        if (jw)
            num[flag][e++] = 1;
        if (e - b > 50)
            b++;
        int len = e - b;
        if (len > 40)
            len = 40;
        int cc[len];
        for (int x = 0; x < len; x++)
            cc[x] = num[flag][e - 1 - x];
        addNode(cc, len, i);
        flag = !flag;
    }
}
//搜索
int msearch(char *in) {
    int len = strlen(in);
    Node* p = head;
    for (int i = 0; i < len; i++) {
        if (p->next[in[i] - '0'] == NULL)
            return -1;
        p = p->next[in[i] - '0'];
    }
    return p->value;
}

int main() {
    getFibAndTree();
    char in[45];
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> in;
        printf("Case #%d: %d\n", i, msearch(in));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值