洛谷P1028 [NOIP 2001 普及组] 数的计算 题解
1.洛谷P1028 [NOIP 2001 普及组] 数的计算 题解
2.洛谷P1464 Function 题解3.洛谷P2440 木材加工 题解4.洛谷P2678 [NOIP 2015 提高组] 跳石头 题解5.洛谷P1314 [NOIP 2011 提高组] 聪明的质监员 题解6.洛谷P1083 [NOIP 2012 提高组] 借教室 题解7.洛谷P1902 刺杀大使 题解8.洛谷P1873 [COCI 2011/2012 #5] EKO / 砍树 题解9.洛谷P2280 [HNOI2003] 激光炸弹 题解10.洛谷P8218 【深进1.例1】求区间和 题解11.洛谷 P1719 最大加权矩形 题解12.洛谷 P2367 语文成绩 题解13.洛谷P1387 最大正方形 题解14.洛谷P1014[NOIP 1999 普及组] Cantor 表 题解15.洛谷P1563 [NOIP 2016 提高组] 玩具谜题 题解16.洛谷P4924 [1007] 魔法少女小Scarlet 题解17.洛谷P1518 [USACO2.4] 两只塔姆沃斯牛 The Tamworth Two 题解18.洛谷P1786 帮贡排序 题解19.洛谷P1990 覆盖墙壁 题解20.洛谷P1010 [NOIP 1998 普及组] 幂次方 题解21.洛谷P1259 黑白棋子的移动 题解22.洛谷P1281 书的复制 题解23.洛谷P1396 营救 题解24.洛谷PP1570 KC 喝咖啡25.洛谷P1661 扩散 题解26.洛谷P1843 奶牛晒衣服 题解P1028 [NOIP 2001 普及组] 数的计算
题目描述
给出正整数 \(n\),要求按如下方式构造数列:
- 只有一个数 \(n\) 的数列是一个合法的数列。
- 在一个合法的数列的末尾加入一个正整数,但是这个正整数不能超过该数列最后一项的一半,可以得到一个新的合法数列。
请你求出,一共有多少个合法的数列。两个合法数列 \(a, b\) 不同当且仅当两数列长度不同或存在一个正整数 \(i \leq |a|\),使得 \(a_i \neq b_i\)。
输入格式
输入只有一行一个整数,表示 \(n\)。
输出格式
输出一行一个整数,表示合法的数列个数。
样例 #1
样例输入 #1
6
样例输出 #1
6
提示
样例 1 解释
满足条件的数列为:
- \(6\)
- \(6, 1\)
- \(6, 2\)
- \(6, 3\)
- \(6, 2, 1\)
- \(6, 3, 1\)
数据规模与约定
对于全部的测试点,保证 \(1 \leq n \leq 10^3\)。
题解
思路
可能同学们一开始会想到使用DFS搜索求解,但是交上去后无法拿到满分,很多测试点会TLE。对此,我们可以采取递归的方法来写题。
通过手动列举前几个\(n\)值所对应的结果,找出规律。我们发现,当\(n\)是一个奇数时,\(n/2\)和\((n-1)/2\)的结果是一样的,即当\(n\)为奇数时,可以转换成求\(n-1\)的结果。于是我们列出了第一个递推式:
\[f(n)=f(n-1) (当n\mod2=1时)
\]
随后,通过构造合法数列的方法,我们可以知道,求\(n\)的结果是所有对于\(1\le i\le n\div 2\)的正整数\(i\)的\(f(i)\)的和加1(因为要包括不在后面加数的单独一个\(n\)的情况),递推式2:
\[f(n)=(\sum_{i=1}^{n\div 2}{f(i)})+1
\]
接下来我们考虑\(f\)的边界条件,当\(n=0\)或\(n=1\)时,只有1个合法数列,所以返回1。
我们就顺利得出了下列递推式:
\[\begin{equation}
\begin{cases}
f(n)=f(n-1),当n\mod2=1 \\
f(n)=f(n)=(\sum\limits_{i=1}^{n\div 2}{f(i)})+1,当n\mod2=0 \\
f(n)=1,当0\le n\le 1
\end{cases}
\end{equation}
\]
代码
#include<bits/stdc++.h> #define endl '\n' using namespace std; int n, vis[1005]; int fun(int x) { if(vis[x]) return vis[x]; // 如果这个问题已经求过了,则直接返回结果 if(x <= 1) return 1; //递推式3,当n<=1,返回1 if(x % 2 == 1) return fun(x - 1); // 递推式1,当n%2==1,返回f(n-1) int ans = 1; for(int i = 1; i <= x / 2; i++) { // 递推式2,当n%2==0,返回f(i)(1<=i<=n/2)的和 int s = fun(i); vis[i] = s; ans += s; } return ans; } int main() { cin >> n; cout << fun(n) << endl; return 0; }
本文作者:2789617221guo
本文链接:https://www.cnblogs.com/2789617221guo/p/18699863
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步