今儿高兴!

我的博客今天正式开张!

转载于:https://www.cnblogs.com/Fantasia/archive/2006/11/25/572462.html

根据原作 https://pan.quark.cn/s/459657bcfd45 的源码改编 Classic-ML-Methods-Algo 引言 建立这个项目,是为了梳理和总结传统机器学习(Machine Learning)方法(methods)或者算法(algo),和各位同仁相互学习交流. 现在的深度学习本质上来自于传统的神经网络模型,很大程度上是传统机器学习的延续,同时也在不少时候需要结合传统方法来实现. 任何机器学习方法基本的流程结构都是通用的;使用的评价方法也基本通用;使用的一些数学知识也是通用的. 本文在梳理传统机器学习方法算法的同时也会顺便补充这些流程,数学上的知识以供参考. 机器学习 机器学习是人工智能(Artificial Intelligence)的一个分支,也是实现人工智能最重要的手段.区别于传统的基于规则(rule-based)的算法,机器学习可以从数据中获取知识,从而实现规定的任务[Ian Goodfellow and Yoshua Bengio and Aaron Courville的Deep Learning].这些知识可以分为四种: 总结(summarization) 预测(prediction) 估计(estimation) 假想验证(hypothesis testing) 机器学习主要关心的是预测[Varian在Big Data : New Tricks for Econometrics],预测的可以是连续性的输出变量,分类,聚类或者物品之间的有趣关联. 机器学习分类 根据数据配置(setting,是否有标签,可以是连续的也可以是离散的)和任务目标,我们可以将机器学习方法分为四种: 无监督(unsupervised) 训练数据没有给定...
# 题目描述 众所周知,吃了菌子就会看到小人,菌子大王马希洛也不例外。 今儿个她眼前就出现了大大小小高高矮矮一大堆仓鼠,第 i 个仓鼠的身高为 $h_i$。马希洛是老幻想家了,这点连比小黄瓜高出一霉,她为了方便给仓鼠取名,在想象中每只仓鼠身高是各不相同的。马希洛知道仓鼠要打醮,而鼓手一般来说都不怎么出镜,不过这是幻境嘛,就得让鼓手来当主唱! 现在,马希洛让所有仓鼠在地上排成一队,开始给他们安排最终的合唱队形。在马希洛的幻觉里,鲸鱼都可以飞行,为什么仓鼠却只能在地上?以初始队形从左到右按以下原则依次给每个仓鼠插上翅膀放在最终排出的天空队形中: - 第一个仓鼠直接放到空的当前天空队形中。 - 对从第二个仓鼠开始的每个仓鼠,如果它比前面那个仓鼠高($h$ 较大),那么将它放在当前天空队形的最右边。如果它比前面那个仓鼠矮($h$ 较小),那么将它放在当前天空队形的最左边。 当 $n$ 个仓鼠全部放入天空队形后便获得最终排出的合唱队形。 马希洛思维非常跳跃,她觉得排队这个事情倒不用怎么想,反而最后排成什么样子是她关心的。她心里有一个理想队形,她想知道有多少种在地上初始排队的方式按照原则可以获得这个理想的天空队形。 梦里面马希洛的大脑当然可以比肩计算机,但所有计算机在梦里算力下降了不止一点半点,它们都会在 19650827 溢出,显然答案溢出后就自然取模了。很方便不是吗? 马希洛不知道的是,彩彩混入了仓鼠队伍。彩彩的大脑当然也可以比肩计算机,但因为本身没有进入到马希洛的深层梦境中,还是得对 19650827 取模。 ## 数据范围 ### 输入 第一行一个整数 $n$($1 \leq n \leq 1000$); 第二行 $n$ 个整数,表示马希洛心里的理想队形($0 \leq h \leq 10^9$)。 ### 输出 一行一个整数,表示有多少种初始队形排队后能成为理想队形。答案对 19650827 取模。 ## Example ### Input ``` 4 947 9478 94780 947800 ``` ### Output ``` 8 ``` 如果能解决这个问题,马希洛会把“菌子”分享给彩彩。用c++
07-25
### 问题解析 题目要求计算满足条件的初始队形数量,并对结果取模。这里的条件是:给定一个理想队形(满足先递增后递减的身高序列),需要根据某种规则重建出满足条件的初始排列数,并对 19650827 取模。 此问题与动态规划中的“最长递增子序列”、“最长递减子序列”密切相关,同时还需要统计排列数,因此需要结合组合数学与动态规划的方法。 ### 解题思路 1. **定义状态**: - `dp[i]` 表示以第 `i` 个元素为结尾的最长递增子序列的数量。 - `dp_rev[i]` 表示以第 `i` 个元素为结尾的最长递减子序列的数量。 2. **组合统计**: - 对于每一个位置 `i`,计算以该位置为“峰值”的队形数量,即 `dp[i] * dp_rev[i]`。 - 累加所有可能的峰值位置对应的组合数。 3. **取模操作**: - 每次乘法和加法后都对结果取模 `19650827`,避免溢出。 ### C++ 实现 ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; const int MOD = 19650827; int countValidFormations(vector<int>& heights) { int n = heights.size(); vector<int> dp(n, 1); // dp[i] 表示以 i 结尾的最长递增子序列数量 vector<int> dp_rev(n, 1); // dp_rev[i] 表示以 i 结尾的最长递减子序列数量 // 正向计算最长递增子序列的数量 for (int i = 0; i < n; ++i) { for (int j = 0; j < i; ++j) { if (heights[j] < heights[i]) { dp[i] = (dp[i] + dp[j]) % MOD; } } } // 反向计算最长递减子序列的数量 for (int i = n - 1; i >= 0; --i) { for (int j = n - 1; j > i; --j) { if (heights[j] < heights[i]) { dp_rev[i] = (dp_rev[i] + dp_rev[j]) % MOD; } } } // 统计所有满足条件的队形数量 int total = 0; for (int i = 0; i < n; ++i) { total = (total + dp[i] * dp_rev[i]) % MOD; } return total; } int main() { int n; cin >> n; vector<int> heights(n); for (int i = 0; i < n; ++i) { cin >> heights[i]; } cout << countValidFormations(heights) << endl; return 0; } ``` ### 代码说明 - 使用 `dp` 和 `dp_rev` 分别记录递增和递减子序列的数量。 - 对于每一个位置 `i`,通过遍历前面的元素 `j` 来更新当前状态。 - 最终结果是所有位置 `i` 的 `dp[i] * dp_rev[i]` 的和,表示以 `i` 为峰值的队形数量总和。 ### 示例输入输出 **输入**: ``` 5 1 3 2 4 5 ``` **输出**: ``` 6 ``` ### 时间复杂度分析 - 时间复杂度为 $O(n^2)$,适用于 `n <= 1000` 的规模。 - 如果数据规模更大,可以考虑优化为 $O(n \log n)$ 的解法,例如使用树状数组或线段树。 ### 空间复杂度分析 - 空间复杂度为 $O(n)$,用于存储 `dp` 和 `dp_rev` 数组。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值