蓝桥杯真题复盘: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++)。
相关推荐
严肃小白兔8 分钟前
MATLAB 数值计算中的精度与误差问题:浮点运算、误差传播与数值稳定性
人工智能·算法·matlab
Hhy_110731 分钟前
《C++深度解构06》手撕 string —— 从底层内存管理到深浅拷贝彻底吃透
c语言·开发语言·c++·学习·visual studio
青少儿编程课堂1 小时前
蓝桥杯青少组图形化省考报名倒计时·全国青少年信息素养大赛·电子学会图形化考级:校园黑白棋人机对战解析
c++·python·算法·bfs·信息学竞赛
YSL0701241 小时前
C++基础
开发语言·c++
eggwyw2 小时前
关于C++为什么不加入垃圾回收机制解析
开发语言·c++
jktantan2 小时前
注解式脱敏:用 Jackson 的 ContextualSerializer 做字段级策略(一)
spring boot·后端·算法·spring cloud·系统架构
曦樂~12 小时前
Cpp面筋
c语言·c++
道尔柯南12 小时前
C++ string 类详解:从常用接口到深拷贝,彻底掌握字符串处理
android·java·c++
Dream it possible!15 小时前
LeetCode 面试经典 150_多维动态规划_交错字符串(97_C++_中等)
算法·leetcode·面试·动态规划
心抵鹊15 小时前
算法之双指针系列(一)
算法·leetcode