溢出与概率——斐波那契(不用大数的做法)
2018-02-03 23:35
232 查看
题目来源https://www.nowcoder.net/acm/contest/71#question C题
此题唯一特色就是数特别大,斐波那契数列的第十万项的值超过longlong可存储的最大范围.
用字符串读取.转为数字发生溢出,高位上的数自动被去除,无法读到完整数,读到的是f(一个不完整的最多20位的longlong形整数)。
然后从斐波那契第一项开始计算第二项,第三项……第i项(第i项同样溢出,一个不完整的最多20位的longlong型整数),每次把第i项这个溢出数和f这个溢出数进行比较,它们由于都是20位左右的数,比如正常不溢出f=1234,溢出后为234;比如正常不溢出,第i项算出来是1234,溢出会去除高项,变为234;而11234,溢出同样变为234,那么为什么f和第i项(实际上溢出了)相等,就能确定原本的f和第i项(不溢出的原本状态)相等呢?这是因为,f和第i项都是longlong型整数,它们最多可达20位,即使溢出,只要后20位相等,那么原本不溢出的数不相等的概率是很低的。
这是为什么呢?因为不是所有数都可以成为斐波那契数,斐波那契数的取得尤其特殊的取得方式(是前两项相加不断推出来的),现在某个大数,问他是斐波那契数的第几项,而通过计算到第i项,我们发现第i项这个大数(溢出被削为20位)和输入的那个大数是相等的(20位嘛),如果这样两个数都不等,也就意味着斐波那契还存在某个更大的数,它的后20位和这个输入的大数的后二十位一样,然而斐波那契函数有奇特的构造方式,那么产生这样的更大的数的概率就更低了。几乎可以忽略这种可能性。
#include <stdio.h> #include<string.h> #define maxn 100001 char s[maxn]; unsigned long long fn = 0; unsigned long long f1 = 1; unsigned long long f2 = 2; unsigned long long f = 0; int main() { while(scanf("%s",s)!=EOF) { int i; fn = 0; f1 = 1; f2 = 2; for(i = 0; s[i]!='\0'; i++) fn = fn*10 + s[i]-'0';//把字符串转化为数字,过程中发生溢出 if(fn==1) printf("1\n"); else if(fn==2) printf("2\n"); else { for(i = 3; i < maxn; i++)//从斐波那切的第一位开始往后算,i就是所求的项数。 { f = f1+f2; f1 = f2; f2 = f;//f在计算过程中发生溢出 if(f==fn)//f和fn(字符串转为数字的那个数),两者都发生了溢出,但竟然可以比较是否相等,原因如最上方 break; } printf("%d\n",i); } } return 0; }
相关文章推荐
- 第八章实验7的第二种做法(不用栈做传递)
- java—数组乘积输入: 一个长度为n的整数数组input 输出: 一个长度为n的数组result,满足result[i] = input数组中,除了input[i] 之外的所有数的乘积,不用考虑溢出例如 input {2, 3, 4, 5} output: {60, 40, 30, 24}
- 网上有一种错误的做法是:因为每一个双连通分量内的点low[]值都是相同的,则dfs()时,对于一条边(u,v),只需low[u]=min(low[u],low[v]),这样就不用缩点,最后求度数的时候
- HihoCoder1164 随机斐波那契(概率DP)
- C++随机数--——生成任意范围内等概率随机数“足够好”的做法
- 调用某类时,不用导此类头文件的做法
- 网上有一种错误的做法是:因为每一个双连通分量内的点low[]值都是相同的,则dfs()时,对于一条边(u,v),只需low[u]=min(low[u],low[v]),这样就不用缩点,最后求度数的时候
- 不用比较运算符,判断int型的a,b两数的大小,考虑溢出问题
- poj 3070 Fibonacci,不用打表的快速斐波那契
- 用Groovy实现判断两个int数值大小(不用比较运算符,考虑溢出)
- 摘要:我们经常会用到递归函数,但是如果递归深度太大时,往往导致栈溢出。而递归深度往往不太容易把握,所以比较安全一点的做法就是:用循环代替递归。文章最后的原文里面讲了如何用10步实现这个过程,相当精彩。本文翻译了这篇文章,并加了自己的一点注释和理解。
- 【Codeforces Round 333 (Div 2)E】【期望DP概率做法 树状数组转前缀和】Kleofáš and the n-thlon n场比赛m个人获得总名次的期望
- 不用乘法,除法和mod运算符来分两个整数。 如果溢出,则返回MAX_INT。
- 费波纳列数列,不用递归的做法
- C++随机数--——生成任意范围内等概率随机数“足够好”的做法
- 不用比较运算符,判断int型的a,b两数的大小,考虑溢出问题
- 水晶报表数据源添加字段,不用重新画报表的做法
- 概率与数理统计4
- 此号不用了
- 【HDU】3076 ssworld VS DDD 概率DP