当前位置:首页 > 技术 > 正文内容

洛谷 P1011 车站问题:斐波那契递推与打表技巧

访客 技术 2026年5月24日 4

本题的核心在于发现人数变化的递推规律。设起始站上车人数为参数 ab,观察各站人数关系:

规律推导

用二元组 (p, q) 表示某量关于 ab 的系数:

站点上车系数下车系数净增系数剩余系数
1(1, 0)(0, 0)(0, 0)(1, 0)
2(0, 1)(0, 1)(0, 0)(1, 0)
3(1, 1)(0, 1)(1, 0)(2, 0)
4(1, 2)(1, 1)(0, 1)(2, 1)
5(2, 3)(1, 2)(1, 1)(3, 2)
6(3, 5)(2, 3)(1, 2)(4, 4)

关键发现:从第3站开始,上车人数系数满足斐波那契递推:

u[i] = u[i-2] + u[i-1]

且下车人数等于前一站上车人数:d[i] = u[i-1]

打表生成程序

预先计算各站系数,存储为三维数组 coef[站点][类型][参数]

#include <cstdio>

int coef[25][5][3];

int main() {
    freopen("table.txt", "w", stdout);
    
    // 初始化前两站
    coef[1][1][1] = 1;  // 第1站上车:a
    coef[1][4][1] = 1;  // 第1站剩余:a
    
    coef[2][1][2] = 1;  // 第2站上车:b
    coef[2][2][2] = 1;  // 第2站下车:b
    coef[2][4][1] = 1;  // 第2站剩余:a
    
    // 递推计算 3~20 站
    for (int i = 3; i <= 20; i++) {
        for (int k = 1; k <= 2; k++) {  // 分别处理a和b的系数
            // 上车 = 前两站上车之和
            coef[i][1][k] = coef[i-2][1][k] + coef[i-1][1][k];
            // 下车 = 前一站上车
            coef[i][2][k] = coef[i-1][1][k];
            // 净增 = 上车 - 下车
            coef[i][3][k] = coef[i][1][k] - coef[i][2][k];
            // 剩余 = 前一站剩余 + 净增
            coef[i][4][k] = coef[i-1][4][k] + coef[i][3][k];
        }
    }
    
    // 输出打表结果
    for (int i = 1; i <= 20; i++) {
        printf("%d:\n", i);
        for (int j = 1; j <= 4; j++) {
            printf("  (%d, %d)\n", coef[i][j][1], coef[i][j][2]);
        }
    }
    return 0;
}

精简后的提交代码

实际只需保留"剩余人数"的系数,将打表结果硬编码:

#include <iostream>
using namespace std;

// 打表结果:remain[i][k] 表示第i+1站剩余人数中a/b的系数
// 索引从0开始,对应第2~20站
int remain[20][2] = {
    {1, 0},    // 第2站
    {2, 0},    // 第3站
    {2, 1},    // 第4站
    {3, 2},    // 第5站
    {4, 4},    // 第6站
    {6, 7},    // 第7站
    {9, 12},   // 第8站
    {14, 20},  // 第9站
    {22, 33},  // 第10站
    {35, 54},  // 第11站
    {56, 88},  // 第12站
    {90, 143}, // 第13站
    {145, 232},// 第14站
    {234, 376},// 第15站
    {378, 609},// 第16站
    {611, 986},// 第17站
    {988, 1596},// 第18站
    {1598, 2583},// 第19站
    {2585, 4180} // 第20站
};

int main() {
    int initA, totalStation, finalCnt, queryStation;
    cin >> initA >> totalStation >> finalCnt >> queryStation;
    
    // 注意:finalCnt是第totalStation站开出后的人数
    // 对应 remain[totalStation-2]
    int idx = totalStation - 2;
    int coefA = remain[idx][0];
    int coefB = remain[idx][1];
    
    // 解出参数b
    int initB = (finalCnt - coefA * initA) / coefB;
    
    // 查询第queryStation站开出后人数
    int ansIdx = queryStation - 2;
    int result = remain[ansIdx][0] * initA + remain[ansIdx][1] * initB;
    
    cout << result << endl;
    return 0;
}

注意事项

  • 数组下标从0开始,站点编号需做偏移转换
  • 第1站开出后剩余人数恒为 initA,第2站为 initA,故打表从第3站(索引0)开始
  • 利用第n站总人数可唯一确定参数b,再回代求任意站人数

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。