洛谷 P1028 数的计算【递推】

简介: P1028 数的计算 题目描述 我们要求找出具有下列性质数的个数(包含输入的自然数n): 先输入一个自然数n(nn; 8 f[1]=1; 9 for(int i=2;i

P1028 数的计算

题目描述

我们要求找出具有下列性质数的个数(包含输入的自然数n):

先输入一个自然数n(n<=1000),然后对此自然数按照如下方法进行处理:

1.不作任何处理;

2.在它的左边加上一个自然数,但该自然数不能超过原数的一半;

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

输入输出格式

输入格式:

一个自然数n(n<=1000)

输出格式:

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

输入输出样例

输入样例#1: 复制
6
输出样例#1: 复制
6

说明

满足条件的数为

6,16,26,126,36,136

题目链接:https://www.luogu.org/problem/show?pid=1028

分析:

就是比如一个数6,然后可以添加一个比6/2小的数(题目是左边,为了好理解就直接添加),然后可以再添加一个比6/2/2小的数,直到0为止。比如一个数7的其中一段递归:

  • 比7/2小的数其中有一个3,新数就可以是73;

  • 比3/2小的数只有一个1,于是新数就是731。

再举个例,12:

  • 比12/2小的数其中有一个6,新数就可以是126;

  • 比6/2小的数中有3、2,新数就可以是1263或1262;

  • 比3小的有1,比2小的也是1,新书就是12631或12621。

这么解释大家应该都看懂了吧。

在打代码之前,我们不妨手动模拟一下

n=0,n=1时,答案显然是1
n=2, ans=2;    n=3,ans=2
n=4,ans=4;    n=5,ans=4
n=6,ans=6;    n=7,ans=6

相信大家也发现了,2n与2n+1(n为非负整数)的答案是一样的 这就是第一个规律

然后我们以n=8为例,手动模拟一下

一共有10组解

8 1 8 2 8 3 8 4 8

1 2 8 1 3 8 1 4 8 2 4 8

1 2 4 8

我打出的东西很像一棵搜索树。。。

当我们把8和8下面的左三棵子树放在一起(即8和下面三列),并将所有的8都改成7,我们能发现,我们得到了n=7时的所有解;

我们再把最右端的子树(即剩下的部分)中的所有8删去,我们得到了n=4时的所有解

就这样,我们可以得到一个递推式,

    f(n)=f(n-1)                //7=8-1

        +f(n/2)                //4=8/2

再结合之前发现的规律

就能得到:

n%2==0时
    f(n)=f(n-1)+f(n/2)
n%2==1时
    f(n)=f(n-1) 然后问题就迎刃而解啦

设f[i]为初始值为i时的满足条件总数,可得f[i]=f[1]+f[2]+f[3]+...+f[i/2];容易想到f[1]=1;

因为f[i]=f[1]+f[2]+f[3]+...+f[i/2] 所以当i为奇数时f[i]=f[i-1],当i为偶数时f[i]=f[i-1]+f[i/2];

然后我们可以手动AC了!

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int f[1001];
 4 int main()
 5 {
 6     int n;
 7     cin>>n;
 8     f[1]=1;
 9     for(int i=2;i<=n;i++)
10     {
11             f[i]=f[i-1];
12             if(i%2==0)
13                 f[i]+=f[i/2];
14     }
15     cout<<f[n];
16     return 0;
17 }

 

目录
相关文章
|
6月前
|
算法 测试技术 C++
【数位dp】【动态规划】C++算法:233.数字 1 的个数
【数位dp】【动态规划】C++算法:233.数字 1 的个数
|
5月前
|
存储
【洛谷 P1255】数楼梯 题解(递归+记忆化搜索+高精度)
这是一个使用动态规划解决的“数楼梯”问题。给定楼梯数`N`,求不同上楼方式的数量。程序通过递归函数`f()`计算,其中`f(x) = f(x - 1) + f(x - 2)`,初始条件`f(1) = 1`,`f(2) = 2`。考虑到数据规模可能很大,使用了高精度加法运算。样例输入`4`,输出`5`。代码中定义了一个存储中间结果的向量`mem`,并提供了一个用于显示高精度数的`printv()`函数。
98 0
|
3月前
|
算法 Java
LeetCode初级算法题:子数组最大平均数+二叉树的最小深度+最长连续递增序列+柠檬水找零
LeetCode初级算法题:子数组最大平均数+二叉树的最小深度+最长连续递增序列+柠檬水找零
43 0
|
6月前
|
算法 测试技术 C#
【数位dp】【数论】【动态规划】2999. 统计强大整数的数目
【数位dp】【数论】【动态规划】2999. 统计强大整数的数目
|
6月前
|
算法 测试技术 C++
【组合数学】【动态规划】【前缀和】1735生成乘积数组的方案数
【组合数学】【动态规划】【前缀和】1735生成乘积数组的方案数
|
6月前
每日一题(最大连续1的个数,完全数计算)
每日一题(最大连续1的个数,完全数计算)
32 0
|
算法 C++ Python
每日算法系列【LeetCode 357】计算各个位数不同的数字个数
每日算法系列【LeetCode 357】计算各个位数不同的数字个数
|
人工智能 算法
刷题之寻找 3 个数的最大乘积和拼数及四平方和
刷题之寻找 3 个数的最大乘积和拼数及四平方和
137 0
|
算法 C++
【基础算法】几种特殊数(素数、公约数、完全数、亲密数) & C++实现
素数又称为质数,它指在一个大于1的自然数中,除了1和它自身外,没法被其他自然数整除的数。比1大,但不是素数的数称为合数。0和1既不是素数,也不是合数。因为素数的分布没有明显的规律,所以在程序中一般根据素数的定义来判断该数是否为素数。例如哥德巴赫猜想:哥德巴赫通过大量的数据猜测,所有不小于6的偶数,都可以表示为两个奇素数之和。后人将其称之为“1+1”。并且,对于每个不小于9的奇数,都可以表示为三个奇素数之和。
333 0
【基础算法】几种特殊数(素数、公约数、完全数、亲密数) & C++实现
|
C++
蓝桥杯练习题四 - 排它平方数(c++)
蓝桥杯练习题四 - 排它平方数(c++)
110 0