菲波那契数列

liangkaiyu 2009-02-22 11:15:56
Description
菲波那契数列是指这样的数列: 数列的第一个和第二个数都为1,接下来每个数都等于前面2个数之和。
给出一个正整数a,要求菲波那契数列中第a个数对1000取模的结果是多少。
Input
第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数a(1 <= a <= 1000000)。
Output
n行,每行输出对应一个输入。输出应是一个正整数,为菲波那契数列中第a个数对1000取模得到的结果。
简单地测试了我的程序,
好像没有什么问题
但超时了,有没有更快的算法
#include "stdio.h"

int fbns(int i){
if (i == 0 || i ==1)
return 1;
else
return (fbns(i-1) + fbns(i-2))%1000;
}
int main(){
long b[1000];
int n, i; //, j = 0;
scanf("%d", &n);
for(i = 0; i < n; i++)
scanf("%ld", &b[i]);

for (i = 0; i < n; i++)
printf("%d\n",fbns(b[i]-1));

return 0;
}



...全文
939 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
yueludragon 2009-02-28
  • 打赏
  • 举报
回复
假如数据不是很大还没有关系,如果大的话需要使用数组进行存储,不过你这里要1000000应该没有关系
jn989 2009-02-24
  • 打赏
  • 举报
回复
变量存储的问题,看一下这个:
http://zhidao.baidu.com/question/50039172.html
zbihong 2009-02-24
  • 打赏
  • 举报
回复
你那递归算法够快了!也是迭代算法咯!!!
lzonline01 2009-02-24
  • 打赏
  • 举报
回复
迭代就可以了,或者用矩阵变换。
wgangqiang 2009-02-24
  • 打赏
  • 举报
回复
最好不要用递归算法来算,函数指针是指数增长的,速度不行,还是用循环算吧
resultridgepole 2009-02-24
  • 打赏
  • 举报
回复
为了不超时,建议楼主本地打表,同时注意数据类型,我写了一个程序如下,应该符合楼主要求:
#include <stdio.h>
#include <stdlib.h>

main()
{
short a[1000001];
long i;
int n;
int j;

a[1]=1;
a[2]=1;

for(i=3; i<=1000000;i++)
a[i]=(a[i-1]+a[i-2])%1000;
scanf("%d",&n);
for (j=1;j<=n;j++)
{
scanf("%ld",&i);
printf("%d\n",a[i]);
}

system("pause");
return 0;
}
morilasi 2009-02-22
  • 打赏
  • 举报
回复

#include <iostream>
using namespace std;

int main()
{
//int num;
//cin>>num;
int num;
while(cin>>num)
{
int arr[2];
arr[0]=arr[1]=1;

for(int i=2;i<=num;i++)
{
arr[i%2]+=arr[(i-1)%2];
}

cout<<arr[num%2]<<endl;
}
}

bfhtian 2009-02-22
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 waizqfor 的回复:]
C/C++ code
void main()
{
long fib[40] = {1,1};
int i;
for(i=2;i<40;i++)
{
 fib[i] = fib[i-1]+fib[i-2];
}
for(i=0;i<40;i++)
{
 printf("F%d==%d\n", i, fib[i]);
}
 return 0;
}
[/Quote]
用数组做就行了
liangkaiyu 2009-02-22
  • 打赏
  • 举报
回复
上面有一段不是本意
	j = b[0];
for (i = 1; i < n; i++)
{
if (j < b[i])
j = b[i]; //找出最后一个数,这样就不一定要算到a[1000000]
}
liangkaiyu 2009-02-22
  • 打赏
  • 举报
回复
遇到问题需要关闭...
#include "stdio.h"
/*int fbns(int i){
//int a[1000000];
if (i == 0 || i ==1)
return 1;
else
return (fbns(i-1) + fbns(i-2))%1000;
}*/
int main(){
long b[1000];
int a[1000000];
int n, i;
long j = 0;

scanf("%d", &n);
for(i = 0; i < n; i++)
scanf("%ld", &b[i]);

for (i = 0; i < n; i++)
{
if (b[j] < b[i])
j = i; //找出最后一个数,这样就不一定要算到a[1000000]
}

a[0] = 1;
a[1] = 1;
for (i = 2; i < j; i++)
a[i] = (a[i-2] + a[i-1])%1000;

for (i = 0; i < n; i++)
// printf("%d\n",fbns(b[i]-1));
printf("%d\n",a[b[i]-1]);

return 0;
}
sxbwelcome 2009-02-22
  • 打赏
  • 举报
回复
你采用的是递归算法,递归下一次时,要将上一次的现场进栈保护,返回到这一层时又要恢复现场,代价较大,所以速度不够
直接顺推【用循环】就可以了 ,而递归是逆推。
ysmashimaro 2009-02-22
  • 打赏
  • 举报
回复
用循环做最快了,或者用栈做。
waizqfor 2009-02-22
  • 打赏
  • 举报
回复

void main()
{
long fib[40] = {1,1};
int i;
for(i=2;i<40;i++)
{
 fib[i] = fib[i-1]+fib[i-2];
}
for(i=0;i<40;i++)
{
 printf("F%d==%d\n", i, fib[i]);
}
 return 0;
}

liangkaiyu 2009-02-22
  • 打赏
  • 举报
回复
谢谢各位的支持和帮助~~
下面的代码能通过
#include "stdio.h"
/*int fbns(int i){
if (i == 0 || i ==1)
return 1;
else
return (fbns(i-1) + fbns(i-2))%1000;
}*/
int a[1000000];
int main(){
long b[1000];

int n, i;
long j ;

scanf("%d", &n);
for(i = 0; i < n; i++)
scanf("%ld", &b[i]);
j = b[0];
for (i = 1; i < n; i++)
{
if (j < b[i])
j = b[i]; //找出最后一个数,这样就不一定要算到a[1000000]
}

a[0] = 1;
a[1] = 1;
for (i = 2; i < j; i++)
a[i] = (a[i-2] + a[i-1])%1000;

for (i = 0; i < n; i++)
// printf("%d\n",fbns(b[i]-1));
printf("%d\n",a[b[i]-1]);

return 0;
}


只是把int a[1000000]放到MAIN()前就可以了
为什么放到MAIN函数里就不行呢?

解决了这个问题就该把帖子结了
liao05050075 2009-02-22
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 sxbwelcome 的回复:]
你采用的是递归算法,递归下一次时,要将上一次的现场进栈保护,返回到这一层时又要恢复现场,代价较大,所以速度不够
直接顺推【用循环】就可以了 ,而递归是逆推。
[/Quote]

其实楼主之所以超时主要不是因为这个,而是楼主的做法存在着大量的重复计算,加个数组做记忆化就该过了。当然,直接递推是最好的做法。
代码如下:


#include "stdio.h"
int ans[1000010];
int fbns(int i){
if(ans[i]!=-1)return ans[i];

if (i == 0 || i ==1)
return 1;
else
return ans[i]=(fbns(i-1) + fbns(i-2))%1000;
}

int main()
{
memset(ans,-1,sizeof ans);

long b[1000];
int n, i; //, j = 0;
scanf("%d", &n);
for(i = 0; i < n; i++)
scanf("%ld", &b[i]);

for (i = 0; i < n; i++)
printf("%d\n",fbns(b[i]-1));

return 0;
}
机智的呆呆 2009-02-22
  • 打赏
  • 举报
回复

#include <iostream>
using namespace std;

template<int n>
class Fbns
{
public:
enum{value=Fbns<n-1>::value+Fbns<n-2>::value};
Fbns(){cout<<value%1000<<endl;}
// Fbns<n-1> f;
};
template<>
class Fbns<0>
{
public:
enum{value=1};
};
template<>
class Fbns<1>
{
public:
enum{value=1};
};

int main(int argc, char *argv[])
{

enum A{a=10,b,c,d,e,f};
Fbns<a> aa;
Fbns<b> bb;
Fbns<c> cc;
Fbns<d> dd;
system("pause");

}

模板元编程~~
liangkaiyu 2009-02-22
  • 打赏
  • 举报
回复
1楼的只是算到前40个数哦
liangkaiyu 2009-02-22
  • 打赏
  • 举报
回复
[Quote=引用楼主 liangkaiyu 的帖子:]
Input
第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数a(1 <= a <= 1000000)。 Output
n行,每行输出对应一个输入。输出应是一个正整数,为菲波那契数列中第a个数对1000取模得到的结果。 [/Quote]

对于这么大的数,应该怎么办呢?
rainbowbaby 2009-02-22
  • 打赏
  • 举报
回复
建议参考下《编程之美》一书,在那会有更多的思路。
leijunyuncyuyan 2009-02-22
  • 打赏
  • 举报
回复
6楼的不错啊
加载更多回复(1)

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧