2022-06-26 华泰证券 Fintech 比赛题解

  • 小华拼单词
  • 股票买卖的最大收益
  • 运货
  • 区间成绩的因子数之和

2022-06-29

小华拼单词

小华拿到了很多个字母,他希望能拼出尽可能多的 “huatai” 单词,你能告诉他最多可以拼出多少个吗?
输入描述
输入 26 个整数 cntcntcnt,分别代表字母 ‘a’ 到字母 ‘z’ 的数量。
1≤cnt≤1091 \leq cnt \leq 10^91≤cnt≤109。
输出描述
一共最多可以拼出 “huatai” 的数量。

一个 “huatai” 单词包含 1 个 hhh,1 个 uuu,2 个 aaa,1 个 ttt 和 1 个 iii。因此我们分别求出各个字母的数量可以拼出多少个 “huatai”,并且根据木桶效应,理应选择最少的那个值。

#include <iostream>
#include <vector>
using namespace std;int main()
{vector<int> cnts(26, 0);for (int i = 0; i < 26; i++)cin >> cnts[i];int ans = 0x7fffffff;ans = min(ans, cnts['h' - 'a']);ans = min(ans, cnts['u' - 'a']);ans = min(ans, cnts['a' - 'a'] / 2); // 1 个 "huatai" 需要 2 个 'a'ans = min(ans, cnts['t' - 'a']);ans = min(ans, cnts['i' - 'a']);cout << ans << endl;return 0;
}

股票买卖的最大收益

给定股票每天变化的价格。初始股票 xxx 手,初始现金 0 元,每天可以任意次买入或卖出,但最多持有 kkk 手股票。请问最后一天结束时,将手中所有股票换算成现金后,能够得到的最大总资产是多少?
输入描述
第一行输入是哪个正整数 nnn,kkk,xxx,分别代表总天数、最大持有股票数目,以及初始股票数目。
第二行输入 nnn 个正整数 aia_iai​,代表股票的每日价格。

题目中没有说清楚 股票必须整买整卖 容易让人造成误解,谨此说明。

根据 贪心 思想,一天中要么卖出所有股票,要么尽可能买进股票才能获得利益最大化,所以每天有 2 种状态,我们称之为 现金流股票流

再运用 动态规划 思想,当天的现金流状态可以从前一天的现金流状态直接得来,也可以从前一天的股票流状态经卖出所有股票得来,究竟是哪 取决于谁最终得到的现金最多。当天的股票流状态则更为复杂,可以用前一天的股票流状态经继续买入股票得来,或是用前一天的现金流状态经直接大幅度买入股票得来,需要特殊考虑的是:最多只能持有 kkk 手股票。因此我们应该优先选择能够获得更多股票数的状态转化而来,若两种状态能够获得的股票数一样时,应该比较哪种状态剩余的现金更多。

#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>using namespace std;struct node {int64_t stock; // 股票数int64_t cash; // 现金数node() {};node(int64_t s, int64_t c) : stock(s), cash(c) {};
};int main()
{int64_t n, k, x; cin >> n >> k >> x;vector<int64_t> price(n);for (int64_t i = 0; i < n; i++)cin >> price[i];vector<vector<node>> dp(n, vector<node>(2)); // 0: 现金流, 1: 股票流dp[0][0] = node(0, x * price[0]);dp[0][1] = node(x, 0);for (int i = 1; i < n; i++) {// 现金流:只须将前一天的现金流和股票流分别转换成现金比较谁多即可dp[i][0] = node(0, max(dp[i - 1][0].stock * price[i] + dp[i - 1][0].cash, dp[i - 1][1].stock * price[i] + dp[i - 1][1].cash));// 股票流:假设将前一天的现金流和股票流尽可能再买入当天的股票。int64_t stock0 = dp[i - 1][0].stock + dp[i - 1][0].cash / price[i], stock1 = dp[i - 1][1].stock + dp[i - 1][1].cash / price[i];int64_t cash0 = dp[i - 1][0].cash % price[i], cash1 = dp[i - 1][1].cash % price[i];if (stock0 > stock1) {if (stock1 >= k) {dp[i][1] = node(k, max((stock0 - k) * price[i] + cash0, (stock1 - k) * price[i] + cash1));} else if (stock0 >= k) {dp[i][1] = node(k, (stock0 - k) * price[i] + cash0);} else {dp[i][1] = node(stock0, cash0);}} else if (stock1 > stock0) {if (stock0 >= k) {dp[i][1] = node(k, max((stock0 - k) * price[i] + cash0, (stock1 - k) * price[i] + cash1));} else if (stock1 >= k) {dp[i][1] = node(k, (stock1 - k) * price[i] + cash1);} else {dp[i][1] = node(stock1, cash1);};} else {// 两种方案得到的股票数一样时,优先考虑剩余现金多的。if (stock0 >= k) {dp[i][1] = node(k, max((stock0 - k) * price[i] + cash0, (stock1 - k) * price[i] + cash1));} else {dp[i][1] = node(stock0, max(cash0, cash1));};};};cout << max(dp[n - 1][0].stock * price[n - 1] + dp[n - 1][0].cash, dp[n - 1][1].stock * price[n - 1] + dp[n - 1][1].cash) << endl;return 0;
}

运货

nnn 个城市由 n−1n - 1n−1 条道路连接起来,城市编号从 111 到 nnn。从城市 uuu 到城市 vvv 的最短路径是唯一确定的,我们定义 uuu 和 vvv 的愉悦值为两个城市间最短路径上的城市编号的最大值,请求出每两两城市间的愉悦值总和并对 109+710^9 + 7109+7 取模。
输入描述
第一行输入一个正整数 nnn,代表城市的数量。
接下来的 n−1n - 1n−1 行,每行输入两个正整数 uuu 和 vvv,代表城市 uuu 和城市 vvv 有一条道路连接。
1≤n≤1051 \leq n \leq 10^51≤n≤105。
1≤u,v≤n1 \leq u, v \leq n1≤u,v≤n。
输出描述
输出一个非负整数,表示小明的总愉悦值对 109+710^9 + 7109+7 取模的值。

枚举两个城市是不现实的,因此我们考虑从编号小的城市开始,不断扩充城市地图。具体地,举个例子,假设现在有 1,2,31,2,31,2,3 是连通的,4,54,54,5 是连通的,6,76,76,7 是连通的,那么考虑城市 888,若存在边 [8,1],[8,7][8, 1], [8, 7][8,1],[8,7],则加入城市 888 后有 1,2,3,6,7,81,2,3,6,7,81,2,3,6,7,8 均是连通的,这里有 C82C_8^2C82​ 条道路,但是原先 1,2,31,2,31,2,3 是连通的有 C32C_3^2C32​ 条道路,原先 7,87,87,8 是连通的有 C22C_2^2C22​ 条道路,因此经过 888 且以 888 为最大值的道路有 C82−C32−C22C_8^2 - C_3^2 - C_2^2C82​−C32​−C22​ 条道路。

我们使用 并查集 来记录各个城市的连通性,并按照编号从小到大的顺序考虑各个城市即可。

注:输入用 scanf() 较快。

#include<vector>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <stdio.h>using namespace std;class UnionSet {vector<int64_t> father;vector<int64_t> rank;
public:UnionSet(int64_t n) {father = vector<int64_t>(n);for (int64_t i = 0; i < n; i++)father[i] = i;rank = vector<int64_t>(n, 1);};int64_t find(int64_t x) {return x == father[x] ? x : find(father[x]);};void to_union(int64_t x, int64_t y) {int fa_x = find(x);int fa_y = find(y);if (rank[fa_x] >= rank[fa_y]) {father[fa_y] = fa_x;rank[fa_x] += rank[fa_y];} else {father[fa_x] = fa_y;rank[fa_y] += rank[fa_x];};};bool compare(int64_t x, int64_t y) {return find(x) == find(y);};int64_t get_rank(int64_t x) {return rank[find(x)];};
};
int main()
{int64_t n, mod = 1e9 + 7; cin >> n;vector<vector<int64_t>> edges(n + 1);for (int64_t i = 1; i <= n; i++) {int64_t u, v; scanf("%lld%lld", &u, &v);edges[max(u, v)].push_back(min(u, v));};UnionSet uni(n + 1);vector<int64_t> cnt(n + 1, 0), ans(n + 1, 0);int64_t ret = 0, r;for (int64_t i = 1; i <= n; i++) {int64_t tt = 0;for (const int64_t& j : edges[i]) {// 如果城市 j 和城市 i 不连通  if (!uni.compare(i, j)) {// 则需要减去这些道路r = uni.get_rank(j);tt += r * (r - 1) / 2;// 连通 i 和 juni.to_union(i, j);};};r = uni.get_rank(i);tt = r * (r - 1) / 2 - tt;ret = (ret + tt * i) % mod;};cout << ret << endl;return 0;
}

区间成绩的因子数之和

给定一个数组,数组中每个数都是 [1,2,3][1,2,3][1,2,3] 中的一个,已知一个区间的权值是该区间所有数乘积的因子数量,求所有区间的权值之和。
输入描述
第一行输入一个正整数 nnn,代表数组的长度。
第二行输入 nnn 个正整数 aia_iai​,代表数组的元素。

动态规划 是必然的,但状态转移方程着实有点难想。大概思路就是:

如果 nums[i]是 111,则当前一个元素的区间是 [1][1][1],会增加 111 个因子,而在 [0,i][0, i][0,i] 区间范围内所有子区间中的 222 的个数总和以及 333 的个数总和都是不变的。

如果 nums[i] 是 222,则当前一个元素的区间是 [2][2][2],会增加 222 个因子,且当前元素会给之前所有含 333 的元素多一个因子,且在 [0,i][0, i][0,i] 区间范围内所有子区间的 222 的个数总和会增加 i+1i + 1i+1。

如果 nums[i] 是 333,则当前一个元素的区间是 [3][3][3],会增加 222 个因子,且当前元素会给之前所有含 222 的元素多一个因子,且在 [0,i][0, i][0,i] 区间范围内所有子区间的 333 的个数总和会增加 i+1i + 1i+1。

#include <iostream>
#include <vector>using namespace std;int main()
{int64_t n; cin >> n;vector<int64_t> nums(n);for(int64_t i = 0; i < n; i++)cin >> nums[i];int64_t mod = 1e9 + 7;vector<vector<int64_t>> dp(n, vector<int64_t>(4, 0));dp[0][0] = (nums[0] > 1) + 1;dp[0][2] = nums[0] == 2;dp[0][3] = nums[0] == 3;for (int64_t i = 1; i < n; i++) {if (nums[i] == 1) {dp[i][0] = (dp[i - 1][0] + 1) % mod;dp[i][2] = dp[i - 1][2];dp[i][3] = dp[i - 1][3];} else if (nums[i] == 2) {dp[i][0] = (dp[i - 1][0] + dp[i - 1][3] + i + 2) % mod;dp[i][2] = (dp[i - 1][2] + i + 1) % mod;dp[i][3] = dp[i - 1][3];} else if (nums[i] == 3) {dp[i][0] = (dp[i - 1][0] + dp[i - 1][2] + i + 2) % mod;dp[i][2] = dp[i - 1][2];dp[i][3] = (dp[i - 1][3] + i + 1) % mod;};};int64_t ans = 0;for (int i = 0; i < n; i++)ans = (ans + dp[i][0]) % mod;cout << (int) ans << endl;return 0;
}

闲来无事参加的比赛,见识到了无数大佬的思维和手速。很遗憾,在比赛结束后两分钟 AC 掉了最后一题没能计入成绩,但可喜的是排名还是进入了前 100,期待之后的决赛吧。最后,欢迎关注我的 GitHub 账号。

2022-06-26 华泰证券 Fintech 比赛题解相关推荐

  1. 2022.06.26 华为od机试真题

    华为od机试真题 1.最长连续子串 2.正方形数量 3.二叉树层次遍历(不会做) 1.最长连续子串 有N个正整数组成的一个序列给定一个整数sum求长度最长的的连续子序列使他们的和等于sum返回次子序列 ...

  2. Python线程指南 ---转自 http://www.cnblogs.com/huxi/archive/2010/06/26/1765808.html

    Python线程指南 ---转自 http://www.cnblogs.com/huxi/archive/2010/06/26/1765808.html 本文介绍了Python对于线程的支持,包括&q ...

  3. 小学奥数 7657 连乘积末尾0的个数-2022.01.26

    http://noi.openjudge.cn/math/7657/ /* 小学奥数 7657 连乘积末尾0的个数-2022.01.26 http://noi.openjudge.cn/math/76 ...

  4. English Learning - Day20 作业打卡 2022.12.26 周一

    English Learning - Day20 作业打卡 2022.12.26 周一 引言 一.给出如下短语的汉语释义 1. a burning house 2. an ag(e)ing popul ...

  5. Windows10 彻底关闭系统更新(2022.12.26更新)

    熊熊亲测有效,2022.12.26更新 一.服务 快捷键Win+R,输入"services.msc",打开"服务",在[常规]选项卡中停止服务并在"启 ...

  6. Hibiscus的脑机接口学习周报(2022/12/26~2022/1/1)

    2022/12/26(星期一) 在学习使用python mne库读取.set类型数据时,遇到了类似如下报错:buffer is too small (来源于Python读取.set格式的脑电数据出现b ...

  7. 笔记:模拟CMOS集成电路设计(拉扎维)第二版--第三章--单级放大器增益(更新2022.12.26)

    目录 共源级 源跟随器 共栅级 共源共栅级 总结(更新2022.12.26) 整理了一些单级放大器电路增益的笔记,按照共源级.源跟随器.共栅级和共源共栅级顺序,分享一下~ 共源级 源跟随器 共栅级 共 ...

  8. 人工智能 | ShowMeAI资讯日报 #2022.06.18

    ShowMeAI日报系列全新升级!覆盖AI人工智能 工具&框架 | 项目&代码 | 博文&分享 | 数据&资源 | 研究&论文 等方向.点击查看 历史文章列表, ...

  9. .net NPOI Excel导入:时间格式2022/5/26导入变成26-5月-2022

    1.问题由来 在做一个导入的需求时,测试导入模板,无论导入模板里的日期设置成何种日期格式到代码中都会提示有不正确的格式化数据,加断点调试发现,导入的日期如:Excel表格中是2022/5/26,断点看 ...

最新文章

  1. DSP-SLAM:具有深度形状先验的面向对象SLAM
  2. RHCE 学习笔记(22) 网络用户
  3. 【转】闲聊Kernel engineer的境界(全)
  4. [蓝桥] 算法提高 扶老奶奶过街
  5. 大数据分析与应用技术国家工程实验室项目通过验收
  6. python怎么另起一行阅读答案_使用Python+Dlib构建人脸识别系统(在Nvidia Jetson Nano 2GB开发板上)...
  7. 830. 较大分组的位置
  8. go - struct
  9. java框架_Java 中几种常用的 RPC 框架介绍
  10. 工作中不要扯虎皮吓唬人
  11. Java Foundation serial ( 一 )
  12. 计算机绘图中有六种方法绘圆,圆的绘制教案
  13. 从零开始学习ThingJS之创建/销毁物体
  14. blast2go下载和本地安装
  15. 用JS 输出 正三角形
  16. 游戏自动化协议测试工具的开发个人思路
  17. 二手交易APP开发主要功能有哪些?(二)
  18. 眼见不一定为实!18个神奇的视错觉,看完不相信眼睛系列
  19. Python代码实现NIST随机性测试
  20. 中国联通客户端被曝Bug:无密码随便登陆

热门文章

  1. 电脑问题处理篇3:解决因内存引起电脑开机长鸣问题
  2. 大学计算机基础教程excel实验报告,大学计算机基础教程excel实验报告
  3. 电视盒子哪个牌子好?【恐龙测评】盘点电视盒子排名
  4. DBeaver下载安装与连接MySQL数据库
  5. 大学计算机绘图课程要带电脑吗,中央广播电视大学开放教育本科机械设计制造及其自动化专业《计算机绘图( 本) 》课程考核说明...
  6. Windows10 + Ubuntu18.04双系统教程及踩坑(Nvidia显卡导致的ubuntu安装以及启动过程中花屏问题)
  7. 个体工商户核名查询_如何查询营业执照核名
  8. 九星连珠用c语言编程,王者模拟战27号更新:九星连珠不再是梦想 贪婪天赋荣升A级...
  9. 2022-02-12生活日志
  10. 偏见的由来-选择性阅读