CSP历年复赛题-P1028 [NOIP2001 普及组] 数的计算

原题链接:https://www.luogu.com.cn/problem/P1028

题意解读:给定n,构造数列,可以用递归或者递推。

解题思路:

1、递归

定义count(n)返回数列的个数

  n==1时,count(n) = 1

  n!=1时,count(n) = 1 + count(1) + count(2) + ...+ count(n/2)

注意,递归会导致大量重复计算,需要用一个hash数组来避免重复计算,否则会超时

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 3005;

long long f[N];

int n;

long long count(int n)
{
    if(f[n]) return f[n]; //如果count(n)已经计算过,直接返回结果
    if(n == 1) return 1;
    long long res = 1;
    for(int i = 1; i <= n / 2; i++)
    {
        res += count(i);
    }
    f[n] = res; //将count(n)的值保存下来,避免重复计算
    return res;
}

int main()
{
    cin >> n;
    cout << count(n);
    return 0;
}

2、递推

我们看n = 6,数列为:

6

6,1

6,2

6,3

6,2,1

6,3,1

n = 5时,数列为:

5

5,1

5,2

5,2,1

相比n=6,缺少了n=3的数列

n=4时,数列为:

4

4,1

4,2

4,2,1

与n=5时一样。

因此,可以推断,令f[i]为i的数列数量

当i是偶数时,f[i] = f[i - 1] + f[i / 2]

当i是奇数时,f[i] = f[i - 1]

初始值f[1] = 1

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 3005;

long long f[N];
int n;

int main()
{
    cin >> n;
    f[1] = 1;
    for(int i = 2; i <= n; i++)
    {
        if(i % 2 == 0) f[i] = f[i - 1] + f[i / 2];
        else f[i] = f[i - 1];
    }
    cout << f[n];
}

 

posted @ 2024-05-21 18:04  五月江城  阅读(47)  评论(0编辑  收藏  举报