• UVa 12333


    题意:

    给定n个(n<=40)数字, 求100000个以内有没有前面n个数字符合给定的数字的fibonacci项, 如果有, 给出最小的fibonacci项, 如果没有, 输出-1。

    分析:

    可以将这个问题分为两个部分:

    ①求出10万个fibonacci数列的前40个数字

    ②查找给定的数在不在这些数字里面

    对于第一个部分, 我们可以模拟竖式加法(可以用滚动数组节省内存), 然后因为只是需要前40位,而且fibonacci数列上升速度很快, 所以我们保留60位的精度就足够了。

    对于第二部分,可以构造字典树,用数组模拟可以避免指针带来的不必要出错。

    #include <bits/stdc++.h>
    using namespace std;
    struct Node
    {
        int id;
        int next[10];
        Node(){
            id = -1;
            for(int i = 0; i < 10; i++)
            {
                next[i] = -1;
            }
        }
    };
    Node trie[4266670];
    int cnt = 0;
    const Node root = trie[cnt++];
    void add_node(const char str[], int id)
    {
        int index = 0;
        for(int i = 0, len = strlen(str); i < len; i++)
        {
            int v = str[i] - '0';
            if((trie[index].next[v] == -1))
            {
                trie[index].next[v] = cnt;
                index = cnt;
                cnt++;
            }
            else {
                    index = trie[index].next[v];//如果存在直接去到下一个节点
            }
            if(trie[index].id == -1){
                trie[index].id = id;
            }
        }
    
    }
    int Find(const char str[])
    {
        int index = 0;
        for(int i = 0, len = strlen(str); i < len; i++)
        {
    
            int v = str[i] - '0';
            if(v < 0) return -1;
            if(trie[index].next[v] == -1)
            {
                return -1;
            }
            index = trie[index].next[v];
        }
        return trie[index].id;
    }
    int main()
    {
        char t[50];
        memset(t,0,sizeof(t));
        int fib[2][30000];
        add_node((char*)"1",0);
        int p, q, s, l;
        s = 0; l = 1;
        fib[0][0] = 1;
        fib[1][0] = 1;
        for(int f = 2; f < 100000; f++){
            p = f&1, q = (f+1) &1; //滚动数组
            for(int i = s; i < l; i++){
                fib[p][i] = fib[p][i] + fib[q][i];
                if(fib[p][i] >= 10){
                    fib[p][i+1]++;
                    fib[p][i] -= 10;//进位了记得要减回来
                    if(i == l-1){
                        l++;//如果最后一位还要进位 那么位数+1
                    }
                }
            }
            if(l - s > 60) s++;//保留前60位的精度
            int cnt = 0;
            for(int i = l - 1; i >= s && cnt < 40; i--)
            {
                t[l-i-1] = fib[p][i]+'0';
                cnt++;
            }
            add_node((char*)t,f);//截取前40个数字构造字典树
            memset(t,0,sizeof(t));
        }
        int tt;
        scanf("%d", &tt);
        int kase = 1;
        char que[50];
        while(tt--)
        {
            scanf("%s", que);
            printf("Case #%d: %d
    ",kase++, Find(que));
        }
    }

     

  • 相关阅读:
    Html.RenderPartial和Html.Partial区别
    SQL Server事务处理
    为什么要使用消息队列(一)
    消息队列的优缺点(三)
    消息队列消息顺序性
    分布式事务之消息队列解决方案
    Solr与tomcat整合,并添加中文分词器
    Solr设置高亮
    Solr执行查询操作
    Lucene使用Filter搜索过滤
  • 原文地址:https://www.cnblogs.com/Jadon97/p/6922619.html
Copyright © 2020-2023  润新知