蓝桥杯真题复盘:Fibonacci 数列与黄金分割(C++ 算法详解)

蓝桥杯真题复盘:Fibonacci 数列与黄金分割(C++ 算法详解)

题目来源 :蓝桥杯2019年第十届省赛真题 - Fibonacci 数列与黄金分割


一、 题目描述

题目描述

Fibonacci 数列是非常著名的数列:

  • F 1 = 1 F1 = 1 F1=1
  • F 2 = 1 F2 = 1 F2=1
  • 对于 i > 3 i > 3 i>3, F i = F i − 1 + F i − 2 Fi = Fi - 1 + Fi - 2 Fi=Fi−1+Fi−2

Fibonacci 数列有一个特殊的性质,前一项与后一项的比值, F i F i + 1 \frac{Fi}{Fi + 1} Fi+1Fi,会趋近于黄金分割。

为了验证这一性质,给定正整数 N N N,请你计算 F N F N + 1 \frac{FN}{FN + 1} FN+1FN,并保留 8 位小数。

输入格式

一个正整数 N N N。 ( 1 ≤ N ≤ 2 , 000 , 000 , 000 ) (1 \le N \le 2,000,000,000) (1≤N≤2,000,000,000)

输出格式

F N F N + 1 \frac{FN}{FN + 1} FN+1FN。答案保留 8 位小数。

样例输入

text 复制代码
2

样例输出

text 复制代码
0.50000000

二、 完整代码

cpp 复制代码
#include <iostream>
#include <cmath>
#include <iomanip>

using namespace std;

int main()
{
    long long n;
    cin >> n;
    
    // 当 N 较小时,通过递推直接计算
    if (n <= 35)
    {
        long long f[40];
        f[1] = 1;
        f[2] = 1;
        for (long long i = 3; i <= n + 1; i++)
        {
            f[i] = f[i - 1] + f[i - 2];
        }
        // 必须显式转换为 double,防止整数相除归零
        double res = (double)f[n] / f[n + 1];
        cout << fixed << setprecision(8) << res << "\n";
    }
    else
    {
        // 当 N 很大时,比值直接趋近于黄金分割常数
        double res = (double)(sqrt(5) - 1) / 2;
        cout << fixed << setprecision(8) << res << "\n";
    }
    
    return 0;
}

三、 我学到的核心细节与避坑指南

在解决这道题的过程中,我踩过了几个非常经典的 C++ 编程与数学陷阱,总结如下:

1. 超大范围数据不能暴力硬算

  • 陷阱:题目给出的 N 高达 2,000,000,000(20 亿)。如果用常规的 for 循环递推 20 亿次,必然会遇到时间超限(TLE);如果开大小为 20 亿的数组,会直接内存超限。
  • 收获:观察数学性质。斐波那契数列相邻两项的比值在 N 增大到一定程度后会迅速收敛并趋近于黄金分割数 (sqrt(5) - 1) / 2 ≈ 0.61803399。因此,采用分段讨论(小范围递推,大范围直接输出极限值)是解决此类大数据范围题目的标准套路。

2. C++ 整数相除的"归零"陷阱

  • 陷阱 :在写 f[n] / f[n + 1] 时,由于两边都是 long long 类型的整数,C++ 会执行整型除法,直接舍弃小数部分。因为前面项中分子小于分母,整型相除结果永远是 0。即便后面套了 setprecision(8),输出也只会是 0.00000000。
  • 收获 :在做除法运算时,必须将其中一个操作数强制转换为浮点数(如 (double)f[n] / f[n + 1]),才能触发浮点数高精度除法。

3. 循环边界的细节把控

  • 陷阱 :递推时如果写成 for(long long i = 3; i < n; i++),当输入 N = 10 时,循环会在 i = 9 停下,导致无法算出所需的 FN 和 FN + 1。
  • 收获 :由于需要用到 FN 和 FN + 1,循环终止条件必须包含 N + 1,即写成 for (long long i = 3; i <= n + 1; i++)。
相关推荐
phoenix@Capricornus1 小时前
LDA 协方差矩阵(MATLAB `fitcdiscr`)
算法·matlab·矩阵
lojox1 小时前
C++ 手写 STL list(双向循环链表)原理剖析与实现
c++·链表·list
青少儿编程课堂1 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会C/C++考级:拓扑排序课程表排课解析
c++·python·算法·bfs·信息学竞赛
暖焰核心2 小时前
二叉搜索树——从插入查到key-value改写
c++
草莓熊Lotso5 小时前
【C++ 基于微服务的即时通讯系统】etcd + brpc 从安装到服务注册发现全链路实战
网络·数据库·c++·redis·微服务·etcd
HPtiger11 小时前
数据结构——选择排序
数据结构·算法·排序算法
康实训11 小时前
老年评估仿真实训平台架构设计与老年人能力评估实训室教学落地实践
大数据·人工智能·算法·实训室·实训室建设
DongQiShanRen11 小时前
六根硬件映射(四):归属澄清、两处不一致与卷十一总表
开发语言·人工智能·算法·rust·哈希算法·集成学习
CCblandy11 小时前
雪花 ID 四个边界实测:时钟回拨重号 500 个,前端 JSON.parse 直接丢精度
后端·python·算法·性能优化·架构