斐波那契数列题型汇总

(注:暂时先记录这些问题,后期会持续更新)

斐波那契数列介绍

特点:头两项均为1,后面任一项都是其前两项之和。

程序在计算中需要用两个变量存储最近产生的两个序列值,且产生了新数据后,两个变量要更新。

问题1:输出斐波那契数列的前十项。

    int i,x1,x2,x;
    x1=1;  //头两项都是1 
    x2=1;
    printf("%6d%6d",x1,x2);
    for(i=1;i<=8;i++){  //循环输出后8项 
        x=x1+x2;  //计算新项 
        printf("%6d",x);
        x1=x2;  //更新x1和x2,为下一次计算新项x作准备
        x2=x; 
    }
    printf("
");
    return 0;

或者:

    int i;
    int fib[10]={1,1};  //数组初始化,生成斐波那契数列前两个数
    
    for(i=2;i<10;i++)
        fib[i]=fib[i-1]+fib[i-2];
    
    for(i=2;i<10;i++){
        printf("%6d",fib[i]);
        if((i+1)%5 == 0)  //每输出5个数就换行
            printf("
"); 
    } 
    return 0;

问题2:根据Fibonacci数列的递推公式求余数

Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1。

当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少。

输入格式

输入包含一个整数n。

输出格式

输出一行,包含一个整数,表示Fn除以10007的余数。

说明:在本题中,答案是要求Fn除以10007的余数,因此我们只要能算出这个余数即可,而不需要先计算出Fn的准确值,再将计算的结果除以10007取余数,直接计算余数往往比先算出原数再取余简单。

样例输入

10

样例输出

55

样例输入

22

样例输出

7704

数据规模与约定

1 <= n <= 1,000,000。
 
由于数值太大,我们要先找到它的周期:
#include <stdio.h>

int main( void )
{
    // f(-1)=1, f(0)=0, f(1)=1; f(n)=[f(n-1)+f(n-1)]%10007
    unsigned cycle = 1;
    for( unsigned a=0,b=1; !(a==1&&b==0); ++cycle )
    {
        unsigned c = (a+b)%10007;
         a = b;
         b = c;
    }

    printf( "cycle = %u
", cycle ); // 20016

    return 0;
}

 输出结果为20016。

此时我们知道,当n=20016时,输出值为0;n=20017时,输出值为1...

所以我们可以写出以下代码:

#include <stdio.h>

int main( void )
 {
     unsigned n;
     scanf( "%u", &n );
     n %= 20016;

     unsigned a=1, b=0;
     while( n-- )
     {
         unsigned c = (a+b)%10007;
         a = b;
         b = c;
     }
     printf( "%u", b );

     return 0;
 }

有位朋友给出了对这道题给出了另外一种解法,在此转述如下:

我通过列举前25个斐波纳契数列及其模10007的余数,发现余数和斐波纳契数列具有相同的性质。

不同的地方就是,如果Fn对应的余数大于了10007,那么这个余数的值是前一个余数加上前一个余数的前一个余数的和模上10007。

比如:F3%10007的余数等于F1%10007的余数加上F2%10007的余数之和%10007。

#include<iostream>
using namespace std;
int main() {
    int n1 = 1, n2 = 1, enter, temp;    
    while(cin >> enter)
    {
        if (enter == 1 || enter == 2)
        {
            cout << n1 << endl;  //如果输入值为1或2,则直接输出值 
            continue;
        }    
        enter -= 2;      //如果不是,就从 N=3 开始计算    
        while (enter--) {
            temp = n2;
            n2 = (n1 + n2) % 10007;  //这个余数的值 ==  前一个余数加上前一个余数的前一个余数的和 % 10007 
            n1 = temp;                    
        }
        cout << n2 << endl;
        n1 = 1;  //重置n1 n2 的值,为下次计算余数做准备 
        n2 = 1;
    }    
    return 0;
}

原文地址:https://www.cnblogs.com/OctoptusLian/p/6380452.html