您的位置:首页 > 其它

溢出与概率——斐波那契(不用大数的做法)

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐