题目:给定一个长度为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. JSP标签和EL表达式

    1.jsp标签: sun原生的,直接jsp使用 <jsp:include> -- 实现页面包含,动态包含 <jsp:include page="/index.jsp&quo ...

  2. System.getProperty()获取系统的相关属性

    我们在编程的过程中有时候需要获取系统的相关属性,今天就让我们一起来学习学习如何获取系统的相关属性 至于System.getProperty(param)中的各个参数的概念请看下表. java.vers ...

  3. linux普通用户home目录锁定

  4. .net core webapi +ddd(领域驱动)+nlog配置+swagger配置 学习笔记(2)

    DDD领域驱动模型设计 什么是DDD 软件开发不是一蹴而就的事情,我们不可能在不了解产品(或行业领域)的前提下进行软件开发,在开发前,通常需要进行大量的业务知识梳理,而后到达软件设计的层面,最后才是开 ...

  5. C++基础之C++编译调试

     C++程序的实现(预处理,编译,连接)Linux平台编译gcc和g++都是GNU的编译器.1.对于.c后缀的文件,gcc把它当做是C程序:g++当做是C++程序:2.对于.cpp后缀的文件,gcc和 ...

  6. LOJ6053 简单的函数(min_25筛)

    题目链接:LOJ 题目大意:从前有个积性函数 $f$ 满足 $f(1)=1,f(p^k)=p\oplus k$.(异或)求其前 $n$ 项的和对 $10^9+7$ 取模的值. $1\le n\le 1 ...

  7. window下安装composer步骤(linux待研究)

    window下安装composer步骤--注意(安装完之后需要重启电脑才能生效) 转发:https://blog.csdn.net/wengedexiaozao/article/details/798 ...

  8. CF 980D Perfect Groups(数论)

    CF 980D Perfect Groups(数论) 一个数组a的子序列划分仅当这样是合法的:每个划分中的任意两个数乘积是完全平方数.定义a的权值为a的最小子序列划分个数.现在给出一个数组b,问权值为 ...

  9. 洛谷P1047 校门外的树

    P1047 校门外的树 题目描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0 ...

  10. ie9下网页设计兼容模式

    个人实践使用:ie9下使用低版本ie兼容模式,在网站第一个页面的<head>标签后使用<meta http-equiv="X-UA-Compatible" con ...