Skip to content

M02786: Pell数列

dp, http://cs101.openjudge.cn/pctbook/M02786/

Pell数列a1, a2, a3, ...的定义是这样的,a1 = 1, a2 = 2, ... , an = 2 * an − 1 + an - 2 (n > 2)。 给出一个正整数k,要求Pell数列的第k项模上32767是多少。

输入

第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数k (1 ≤ k < 1000000)。

输出

n行,每行输出对应一个输入。输出应是一个非负整数。

样例输入

2
1
8

样例输出

1
408

可以用尾递归优化。

将递归函数改写成尾递归形式的关键在于确保递归调用是函数的最后一个动作,并且所有必要的状态信息都通过参数传递。对于 pell 函数,可以使用两个辅助参数来保存前两个佩尔数的值,从而实现尾递归。

尾递归优化:C++ 编译器通常会优化尾递归,因此这种实现方式在处理大范围的 n 时通常不会遇到栈溢出的问题。Python 的官方解释器 CPython 并不支持尾递归优化。

cpp
#include <iostream>
#include <vector>

const int MOD = 32767;

// 尾递归函数
int pell_tail(int n, int a = 1, int b = 2) {
    if (n == 1) {
        return a;
    }
    if (n == 2) {
        return b;
    }
    return pell_tail(n - 1, b, (2 * b + a) % MOD);
}

int main() {
    const int MAX_N = 1000000;
    std::vector<int> dp(MAX_N, 0);

    int n;
    std::cin >> n;

    for (int i = 0; i < n; ++i) {
        int k;
        std::cin >> k;

        if (dp[k] != 0) {
            std::cout << dp[k] << std::endl;
        } else {
            dp[k] = pell_tail(k) % MOD;
            std::cout << dp[k] << std::endl;
        }
    }

    return 0;
}