洛谷刷题记录(2026-8-20)P1028 [NOIP 2001 普及组] 数的计算

3 阅读1分钟

P1028 [NOIP 2001 普及组] 数的计算

题目描述

给出正整数 nn,要求按如下方式构造数列:

  1. 只有一个数 nn 的数列是一个合法的数列。
  2. 在一个合法的数列的末尾加入一个正整数,但是这个正整数不能超过该数列最后一项的一半,可以得到一个新的合法数列。

请你求出,一共有多少个合法的数列。两个合法数列 a,ba, b 不同当且仅当两数列长度不同或存在一个正整数 iai \leq |a|,使得 aibia_i \neq b_i

输入格式

输入只有一行一个整数,表示 nn

输出格式

输出一行一个整数,表示合法的数列个数。

输入输出样例 #1

输入 #1

6

输出 #1

6

说明/提示

样例 1 解释

满足条件的数列为:

  • 66
  • 6,16, 1
  • 6,26, 2
  • 6,36, 3
  • 6,2,16, 2, 1
  • 6,3,16, 3, 1

数据规模与约定

对于全部的测试点,保证 1n1031 \leq n \leq 10^3

解题:

学到真东西了:为了应对超时的问题:我们可以采用空间换时间的方法(记忆化递归)

#include<bits/stdc++.h>
using namespace std;
//记忆化递归
#define N 10005
int mem[N] = {0};
int f(int n)
{
    if(mem[n]!=0) return mem[n];//关键步骤
    if(n==1)
    {
        return mem[n] = 1;

    }
    if(n==2)
    {
        return mem[n] = 2;
    }
    if(n==3)
    {
        return mem[n] = 2;
    }

    int result = 1;
    for(int i=1;i<=n/2;i++)
    {
        result+=f(i);
    }
    return mem[n] = result;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);

    int n;
    cin >> n;
    cout << f(n);

    return 0;
}