多组询问共享同一个数列:一次线性递推把斐波那契尾三位预计算到 max(a),之后每问 O(1) 查表。
OJ: roj
题目 ID: 1188
难度:入门
标签:入门递推数学python
创建: 2026-09-29 22:38
更新: 2026-10-05 04:48
题目描述
菲波那契数列:
第一行是组数
样例输入(每组一行):4 5 2 19 1,样例输出:5 1 181 1。
思路
多组询问共享同一个数列:先一次线性递推到
参考代码
Python 版:
python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-09-29 22:38
# update_at: 2026-09-29 22:38
import sys
MOD = 1000 # 题目要求的模数
def fib_table(limit: int) -> list[int]:
"""fib[i] = 第 i 个斐波那契数对 1000 取模,下标从 1 开始,只算到 limit。"""
fib = [0, 1, 1] # f(1) = f(2) = 1,占住下标 0/1/2
for i in range(3, limit + 1):
fib.append((fib[i - 1] + fib[i - 2]) % MOD) # 每步取模,数值不溢出、表恒为三位数以内
return fib
def solve() -> None:
data = iter(map(int, sys.stdin.buffer.read().split()))
T = next(data) # 测试组数
queries = [next(data) for _ in range(T)] # 先收齐全部询问,才知道要预计算到哪个位置
fib = fib_table(max(queries)) # 一次线性递推,所有询问共享同一张表
print('\n'.join(map(str, (fib[a] for a in queries))))
if __name__ == "__main__":
solve()C++ 版(同一算法):
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-10-05 04:48
* update_at: 2026-10-05 04:48
*/
#include <cstdio>
typedef long long ll;
const int MAXA = 1000000 + 5;
const int MOD = 1000;
// fib[i] = 菲波那契数列第 i 项对 1000 取模的结果
ll fib[MAXA];
int main() {
// 预计算:所有询问共享同一张表,先递推到最大的可能下标
fib[1] = 1;
fib[2] = 1;
for (int i = 3; i <= MAXA - 5; ++i) {
fib[i] = (fib[i - 1] + fib[i - 2]) % MOD; // 同余对加法封闭,边算边取模
}
int n;
if (scanf("%d", &n) != 1) return 0;
for (int i = 1; i <= n; ++i) {
int a;
scanf("%d", &a);
printf("%lld\n", fib[a]); // 每问 O(1) 查表
}
return 0;
}