洛谷题单【算法1-4】递推与递归——P1028

184 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情

题单名称

【算法1-4】递推与递归

P1028 [NOIP2001 普及组] 数的计算

题目描述

我们要求找出具有下列性质数的个数(包含输入的正整数 nn)。

先输入一个正整数 nnn1000n \le 1000),然后对此正整数按照如下方法进行处理:

  1. 不作任何处理;

  2. 在它的左边拼接一个正整数,但该正整数不能超过原数,或者是上一个被拼接的数的一半;

  3. 加上数后,继续按此规则进行处理,直到不能再加正整数为止。

输入格式

一行,一个正整数 nnn1000n \le 1000)。

输出格式

一个整数,表示具有该性质数的个数。

样例 #1

样例输入 #1

6

样例输出 #1

6

提示

【样例解释】

满足条件的数为:66161626261261263636136136

【题目来源】

NOIP 2001 普及组第一题

思路

这题是看了题解才做出来的,真的巧妙

递推式在代码注释里,思想很简单

设一维数组f[i],代表n=i的情况数

就是利用前面数字的情况之和,也就是前缀和,再加上已有数字就构成了我们需要求的数字,注意还需要再加上单数字n的一种情况,就构成了f[n]

递推式为f[i] = f[1] + f[2] + ... + f[i/2]

代码

// P1028 [NOIP2001 普及组] 数的计算
// f[i]表示n=i的情况数
// 可以得到递推式,就是f[i] = f[1] + f[2] + ... + f[i/2]
#include <bits/stdc++.h>
using namespace std;

int main(int argc, char const *argv[])
{
    int n;
    cin >> n;
    
    int *f = new int[1010]();
    // f[0] = 0;
    // f[1] = 1;
    // int f[1010] = {0,1};
    for(int i=2; i<=1000; i++){
        for(int j=1; j<=i/2; j++)
            f[i] += f[j];
        f[i]++;
    }
    cout << f[n];
    return 0;
}