zoukankan      html  css  js  c++  java
  • UVA

    题目:给定一个长度为40的数字,问其是否在前100000项fibonacci数的前缀

    因为是前缀,容易想到字典树,同时因为数字的长度只有40,所以我们只要把fib数的前40位加入字典树即可。这里主要讨论下怎么得到fib数的前40位。

    首先,因为没可能每一项的fib都求出来的了。空间都存不下来。所以,只能够缩小规模,有个明显的道理,用每个fib的前60项相加取前40即可。为什么呢?因为没有后效性,后面的项相加不会影响到前40项。就是你有40--60这些项来缓冲就够了,这些才是主要的进位项。后面的相当于无穷小,影响不大。可以理解成误差把。。。两个浮点数差值不超过eps就相等,一样的意思。

    所以,我们要做的是:

    如果F1 和 F2 是大于40位数字的,那么我们就取前60位相加就好了,但是有一个很坑爹很坑爹的地方,就是:假如现在是取前3位吧,然后我取4位来消除误差(其实是不够的,我只是举例子)一个数字是123456,另一个是7894561,这样的话,大家都大于4位啊,但是位数不同啊,你没理由取1234+7894吧,这样就直接wa啊。123456 + 7894561 = 8018017.所以应该是取7894和123相加啊。

    那么怎么知道那个是大那个是小啊,什么时候多一位什么时候位数没关系啊?,经测试,如果你一直取相同位数相加的话,会在284项时GG,不要问我怎么知道的,我找了一天的数据。

    首先要知道的是,肯定是F2先到达60项的,因为F2绝对比F1大嘛。。所以,当F2到达61项的时候,我就要把F2的第61项砍掉,这个时候F2的项数变小了,同时,如果F1比F2少一位的,就是60位,会发生刚才那种坑爹的情况,所以这个时候也要把F1的第60位砍掉。不然就发生刚才的情况

    那么如果都是61位呢?没事,F2都砍了,F1也砍。不然F1就比F2多啦。

    所以是 if (lenstr2 > dd)  str1[lenstr1] = str2[lenstr2]='';//F2先到达,要砍同时砍   dd=60

    注意不能分开判断

    // if (lenstr1>dd) str1[lenstr1]='';
    // if (lenstr2>dd) str2[lenstr2]=''; /gg的

    为什么呢?很简单,因为F1=60(不大于dd),而F2=61(大于dd)砍掉了一位,这样就不行了,坑爹情况出现

    然后说一下后效性,F1+F2 = F3,这个F3有61位怎么办?一样,循环,然后继续砍掉,,所以我一直保持了F2在60位(因为每次相加最多能增加一位,而增加后,我又砍掉了。不增加,我不砍就是了。),而F1,可能59位(坑爹情况),可能60位。

    好累,这题想了好久。

    抓住一点的就是,当他超过60位,要砍项,str[lenstr]='';把str[lenstr]这一项砍掉了。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    const int maxn=1e6;
    const int N=10;//26个小写字母
    struct node
    {
        //int flag;//标记以这个字母结尾为一个单词
        int count;//标记以这个字母结尾为一个前缀
        struct node *pNext[N];//26枚字符指针
    } tree[maxn*N]; //大小通常设为 单词个数*单词长度
    int t;//表明现在用到了那个节点
    struct node *create ()
    {
        //需要新开一个字符节点,就是有abc这样,插入abd,则d需要新开节点
        struct node *p=&tree[t++];
        //p->flag=0;    //初始值为0,不是整个单词
        p->count=1;    //前缀是必须的,本身就是一个了
        for (int i=0; i<N; i++)
        {
            p->pNext[i]=NULL;//初始化指针
        }
        return p;
    }
    void insert (struct node **T,char str[],int cnt)
    {
        struct node *p = *T;
        if (p==NULL)
        {
            p=*T=create();
        }
    //    int lenstr = strlen
        for (int i=1; str[i] && i <= 42; ++i)
        {
            int id = str[i]-'0';
            if (!p->pNext[id])
            {
                p->pNext[id]=create();
                p->pNext[id]->count = cnt;
            }
            p = p->pNext[id];
        }
        if (!p->count) p->count = cnt;
    }
    int find (struct node *T,char str[])
    {
        if (T==NULL) return -1;
        struct node *p = T;
        for (int i=1; str[i]; ++i)
        {
            int id = str[i]-'0';
            if (!p->pNext[id]) return -1;
            p = p->pNext[id];
        }
        return p->count;
    }
    
    int b[300]= {0}; //maxn关键,栈分配,系统帮你释放,要时间,不乱开
    void bigadd (char str1[],char str2[],char str3[])
    {
        int len1=strlen(str1+1);
        int len2=strlen(str2+1);
        //int b[300]= {0}; //maxn关键,栈分配,系统帮你释放,要时间,不乱开
        memset(b,0,sizeof (b));
        int i=len1;
        int j=len2;
        int h=1;
        while (i>=1&&j>=1)
        {
            b[h++]=str1[i--]-'0'+str2[j--]-'0';
        }
        while (i>=1)
        {
            b[h++]=str1[i--]-'0';
        }
        while (j>=1)
        {
            b[h++]=str2[j--]-'0';
        }
        for (int i=1; i<h; i++)
        {
            if (b[i]>=10)
            {
                b[i+1]++;
                b[i]-=10;
            }
        }
        if (!b[h])
        {
            h--;
        }
        int t=h;
        for (int i=1; i<=h; i++)
        {
            str3[t--]=b[i]+'0';
        }
        str3[h+1]=''; //一定要手动结束
        return ;
    }
    struct node *T = NULL;
    char str1[1000],str2[1000],ans[1000];
    void init ()
    {
        str1[1]='1';
        str1[2]='';
        insert(&T,str1,1);
        str2[1]='1';
        str2[2]='';
        insert(&T,str2,2);
        int lenstr1=1,lenstr2=1;
        int dd=60;
        for (int i=2; i<100000; ++i)
        {
            lenstr1 = strlen(str1+1);
            lenstr2 = strlen(str2+1);
    //        if (lenstr1>=dd) str1[lenstr1]='';
    //        if (lenstr2>=dd) str2[lenstr2]='';  /gg的
            if (lenstr2 > dd)
            {
                str1[lenstr1] = str2[lenstr2]='';//砍项
                //str1[dd+1] = str2[dd+1] = '';
                //考虑下为什么不行,因为一直都是60项了
            }
    //        printf ("%s
    %s
    ",str1+1,str2+1);
    //        lenstr1 = strlen(str1+1);
    //        lenstr2 = strlen(str2+1);
    //        printf ("%d %d
    ",lenstr1,lenstr2);
            bigadd(str1,str2,ans);
            insert(&T,ans,i+1);
            strcpy(str1+1,str2+1);
            strcpy(str2+1,ans+1);
    //
    //        printf ("
    ");
    //        printf ("%s [%d]
    ",ans+1,i);
    //        printf ("
    ");
        }
    
        return ;
    }
    int gg;
    void work ()
    {
        scanf("%s",str1+1);
        int t=find(T,str1);
    
        if (t!=-1) --t;
        printf ("Case #%d: %d
    ",++gg,t);
        return ;
    }
    int main()
    {
    #ifdef local
        freopen("data.txt","r",stdin);
    #endif
        init();
        int t;
        scanf("%d",&t);
        while (t--) work();
        return 0;
    }
    View Code
  • 相关阅读:
    深度学习简介(一)——卷积神经网络
    caffe简易上手指南(三)—— 使用模型进行fine tune
    caffe简易上手指南(二)—— 训练我们自己的数据
    caffe简易上手指南(一)—— 运行cifar例子
    三星手机调用系统相机问题整理及解决方案
    android开发无障碍app
    iOS(Swift) TextField限制输入文本的长度(不是字数)
    Android开发经验记录
    Android开源滤镜 仿instagram
    Octave下载
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/5801131.html
Copyright © 2011-2022 走看看