题目:给定一个长度为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]='\0';//F2先到达,要砍同时砍   dd=60

注意不能分开判断

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

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

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

好累,这题想了好久。

抓住一点的就是,当他超过60位,要砍项,str[lenstr]='\0';把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=;//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=; //前缀是必须的,本身就是一个了
for (int i=; 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=; str[i] && i <= ; ++i)
{
int id = str[i]-'';
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 -;
struct node *p = T;
for (int i=; str[i]; ++i)
{
int id = str[i]-'';
if (!p->pNext[id]) return -;
p = p->pNext[id];
}
return p->count;
} int b[]= {}; //maxn关键,栈分配,系统帮你释放,要时间,不乱开
void bigadd (char str1[],char str2[],char str3[])
{
int len1=strlen(str1+);
int len2=strlen(str2+);
//int b[300]= {0}; //maxn关键,栈分配,系统帮你释放,要时间,不乱开
memset(b,,sizeof (b));
int i=len1;
int j=len2;
int h=;
while (i>=&&j>=)
{
b[h++]=str1[i--]-''+str2[j--]-'';
}
while (i>=)
{
b[h++]=str1[i--]-'';
}
while (j>=)
{
b[h++]=str2[j--]-'';
}
for (int i=; i<h; i++)
{
if (b[i]>=)
{
b[i+]++;
b[i]-=;
}
}
if (!b[h])
{
h--;
}
int t=h;
for (int i=; i<=h; i++)
{
str3[t--]=b[i]+'';
}
str3[h+]='\0'; //一定要手动结束
return ;
}
struct node *T = NULL;
char str1[],str2[],ans[];
void init ()
{
str1[]='';
str1[]='\0';
insert(&T,str1,);
str2[]='';
str2[]='\0';
insert(&T,str2,);
int lenstr1=,lenstr2=;
int dd=;
for (int i=; i<; ++i)
{
lenstr1 = strlen(str1+);
lenstr2 = strlen(str2+);
// if (lenstr1>=dd) str1[lenstr1]='\0';
// if (lenstr2>=dd) str2[lenstr2]='\0'; /gg的
if (lenstr2 > dd)
{
str1[lenstr1] = str2[lenstr2]='\0';//砍项
//str1[dd+1] = str2[dd+1] = '\0';
//考虑下为什么不行,因为一直都是60项了
}
// printf ("%s\n%s\n",str1+1,str2+1);
// lenstr1 = strlen(str1+1);
// lenstr2 = strlen(str2+1);
// printf ("%d %d\n",lenstr1,lenstr2);
bigadd(str1,str2,ans);
insert(&T,ans,i+);
strcpy(str1+,str2+);
strcpy(str2+,ans+);
//
// printf ("\n");
// printf ("%s [%d]\n",ans+1,i);
// printf ("\n");
} return ;
}
int gg;
void work ()
{
scanf("%s",str1+);
int t=find(T,str1); if (t!=-) --t;
printf ("Case #%d: %d\n",++gg,t);
return ;
}
int main()
{
#ifdef local
freopen("data.txt","r",stdin);
#endif
init();
int t;
scanf("%d",&t);
while (t--) work();
return ;
}

UVA - 12333 Revenge of Fibonacci 高精度加法 + 字典树的更多相关文章

  1. UVA - 12333 Revenge of Fibonacci (大数 字典树)

    The well-known Fibonacci sequence is defined as following: F(0) = F(1) = 1 F(n) = F(n − 1) + F(n − 2 ...

  2. UVa 12333 - Revenge of Fibonacci manweifc(模拟加法竖式 & 字典树)

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

  3. UVA 12333 Revenge of Fibonacci

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  4. UVa 12333 Revenge of Fibonacci (字典树+大数)

    题意:给定一个长度小于40的序列,问你那是Fib数列的哪一项的前缀. 析:首先用大数把Fib数列的前100000-1项算出来,注意,一定不能是100000,要不然会WA的,然后每个数取前40位,不足4 ...

  5. HDU 4099 Revenge of Fibonacci(高精度+字典树)

    题意:对给定前缀(长度不超过40),找到一个最小的n,使得Fibonacci(n)前缀与给定前缀相同,如果在[0,99999]内找不到解,输出-1. 思路:用高精度加法计算斐波那契数列,因为给定前缀长 ...

  6. UVA 11732 strcmp() Anyone? (压缩版字典树)

    题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...

  7. HDU 4099 Revenge of Fibonacci (数学+字典数)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4099 这个题目就是一个坑或. 题意:给你不超过40的一串数字,问你这串数字是Fibonacci多少的开头 ...

  8. fibonacci高精度加法

    A Fibonacci sequence is calculated by adding the previous two members the sequence, with the first t ...

  9. UVA-12333 Revenge of Fibonacci(竖式加法模拟 & 字典树)

    题目: 给出一个斐波那契数字的前缀,问第一个有这个前缀的数字在斐波那契数列中是第几个. 思路: 紫书提示:本题有一定效率要求.如果高精度代码比较慢,可能会超时. 利用滚动数组和竖式加法来模拟斐波那契相 ...

随机推荐

  1. bzoj 4372 烁烁的游戏 —— 动态点分治+树状数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4372 本以为和 bzoj3730 一样,可以直接双倍经验了: 但要注意一下,树状数组不能查询 ...

  2. C#调试信息打印到输出窗口

    System.Diagnostics.Debug.WriteLine("aaaa");

  3. Linq to Object之非延迟标准查询操作符

    非延时标准查询操作符是指不具备延时查询特性的标准查询操作符,这些操作符一般用于辅助延时标准查询操作符使用. 1.ToArray操作符 ToArray操作符用于将一个输入序列转换成一个数组. 方法原型: ...

  4. 加减 script函数初识

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. .clearfix:after

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. 使用LookAndFeel为界面更换皮肤

    ----------------siwuxie095                             在 Windows 系统中,默认的 Java 运行环境(JRE)会为当前的窗体程序 指定一 ...

  7. JSK 糟糕的bug

    传送门 题目居然复制不了(QAQ) 分析 TrieJSK已经2比较详细了,就不再单独写博客了,此题相较于Trie模板有一点不同,此题要求比较前缀却没有规定前面是后面的前缀还是后面是前面的前缀,所以我们 ...

  8. SpringMVC的国际化

    关于SpringMVC的国际化,http://www.cnblogs.com/liukemng/p/3750117.html这篇文章已经讲的很好了.它讲了有如下几种国际化方式 1:基于Http的hea ...

  9. SqlParameter用法

    if (id != null) { sql = @"update [User] set Username = @Username, Password = @Password, Type = ...

  10. [CentOS7] iconv编程转换

    声明:本文主要总结自:鸟哥的Linux私房菜-第九章.vim 程式編輯器,如有侵权,请通知博主 (-- 源自鸟哥的私房菜) 首先用Notepad++新建个文件来做这个实验,在Windows平台下新建个 ...