当前位置: 首页 > news >正文

2024.3.2 训练记录(6)

文章目录

  • CF 1922E Increasing Subsequences
  • CF 1915G Bicycles
  • CF 1934B Yet Another Coin Problem
  • CF 1934C Find a Mine
  • CF 1912K Kim's Quest
  • CF 161D Distance in Tree
  • CF 1509C The Sports Festival
  • CF 1398D Colored Rectangles

CF 1922E Increasing Subsequences

题目链接

很容易发现,一段长为 i 的上升序列有 2 i 2^i 2i 的贡献(包括空串)

所以按位考虑,先考虑最高位的1,后面的递减给出贡献就可以

这一题学到的是用到log2最好使用 __lg()

#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;const int N = 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;void solve()
{int n;cin >> n;int tmp = __lg(n);vector<int> ans;for (int i = 0; i < tmp; i ++ ) ans.push_back(i);for (int i = tmp - 1; i >= 0; i -- )if ((n >> i) & 1) ans.push_back(i);cout << ans.size() << '\n';for (auto t : ans) cout << t << ' ';cout << '\n';
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t = 1;cin >> t;while (t -- ){solve();}
}

CF 1915G Bicycles

题目链接

比想象中简单的带状态表示的低智dijkstra

再添加一维保存当前最小的s即可

#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;const int N = 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;void solve()
{int n, m;cin >> n >> m;vector<vector<PII>> g(n + 1);while (m -- ){int u, v, w;cin >> u >> v >> w;g[u].push_back({v, w});g[v].push_back({u, w});}vector<vector<int>> dist(n + 1, vector<int>(1010, INF));vector<vector<bool>> st(n + 1, vector<bool>(1010));vector<int> s(n + 1);for (int i = 1; i <= n; i ++ ) cin >> s[i];priority_queue<PIII, vector<PIII>, greater<PIII>> q; // 距离 当前点 最小的sdist[1][s[1]] = 0;q.push({0, {1, s[1]}});while (q.size()){auto t = q.top();q.pop();int dd = t.first, ver = t.second.first, mins = t.second.second;if (st[ver][mins]) continue;st[ver][mins] = true;for (int i = 0; i < g[ver].size(); i ++ ){int j = g[ver][i].first, d = g[ver][i].second;int ns = min(s[j], mins);if (dist[j][ns] > dd + mins * d){dist[j][ns] = dd + mins * d;q.push({dist[j][ns], {j, ns}});}}}int ans = INF;for (int i = 1; i <= 1000; i ++ ) ans = min(ans, dist[n][i]);cout << ans << '\n';
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t = 1;cin >> t;while (t -- ){solve();}
}

CF 1934B Yet Another Coin Problem

题目链接

本来想用dp,但是一看范围好大就不敢用,然后想到是不是先预处理一下小一点的数,然后大的数多出来的部分全部用15,但是觉得这样写好莫名其妙就没写,赛后发现就是这样qaq

#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;const int N = 1e3 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;int p[N];void solve()
{int n;cin >> n;if (n <= N){cout << p[n] << '\n';return;}int ans = 0;int tmp = n / 15;ans += tmp - 15;n = n % 15 + 15 * 15;ans += p[n];cout << ans << '\n';
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);for (int i = 1; i <= N; i ++ ) p[i] = INF;p[1] = 1, p[3] = 1, p[6] = 1, p[10] = 1, p[15] = 1;for (int i = 2; i <= N; i ++ ){if (i - 1 > 0) p[i] = min(p[i - 1] + 1, p[i]);if (i - 3 > 0) p[i] = min(p[i - 3] + 1, p[i]);if (i - 6 > 0) p[i] = min(p[i - 6] + 1, p[i]);if (i - 10 > 0) p[i] = min(p[i - 10] + 1, p[i]);if (i - 15 > 0) p[i] = min(p[i - 15] + 1, p[i]);}int t = 1;cin >> t;while (t -- ){solve();}
}

CF 1934C Find a Mine

题目链接、

因为不太会找两条线的交点于是用循环一个个判断是不是(别骂了。。。

于是成功T的很惨

后来发现数据范围太大了,没法用这个方法找交点水过去,于是开始解方程组,交点解出来了又忘记判断是不是在合法范围内。。。

大概思路就是先判断左上角的点,然后判断右下角的点,这样可以把两个地雷锁定在一条or两条线上,第三次判断左下角的点,判断这个顶点产生的一条线与前两次判断产生的一条or两条线会形成一个or两个交点,第四次询问其中的一个交点,是的话直接输出,不是就输出另一个交点

发现交互题比其他题型要简单(
特别是询问次数少的,次数越少越简单

#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;const int N = 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;void solve()
{int n, m;cin >> n >> m;cout << "? " << 1 << ' ' << 1 << endl;int a, b;cin >> a;if (a == 0){cout << "! 1 1" << endl;return;}int k1 = -2 - a;cout << "? " << n << ' ' << m << endl;cin >> b;if (b == 0){cout << "! " << n << ' ' << m << endl;return;}int k2 = b - n - m;cout << "? " << n << ' ' << 1 << endl;int c;cin >> c;if (c == 0){cout << "! " << n << ' ' << 1 << endl;return;}int x = n - c, y = 1;int k3 = x - y;if ((k3 - k1) % 2 == 0){int xx = (k3 - k1) / 2;int yy = -xx - k1;if (xx >= 1 && xx <= n && yy >= 1 && yy <= m){cout << "? " << xx << ' ' << yy << endl;int d;cin >> d;if (d == 0){cout << "! " << xx << ' ' << yy << endl;return;}}}int xx = (k3 - k2) / 2;int yy = -xx - k2;cout << "! " << xx << ' ' << yy << endl;
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t = 1;cin >> t;while (t -- ){solve();}
}

CF 1912K Kim’s Quest

题目链接

求方案数的问题,首先要能考虑到两种方法:

  • 组合数学
  • 动态规划

因为这道题的限制比较复杂,用组合数学非常困难,于是想到dp

奇偶性,和具体的数是多少无关,所以输入a的时候就把转换成奇偶,奇数1偶数0

dp[i][j][k] 表示前 i 个数中,最后一位是 k,倒数第二位是 j 的方案数

具体还是看代码吧,也还没有完全想清楚

#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;const int N = 10;
const int mod = 998244353;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;void solve()
{int n;cin >> n;vector<int> a(n + 1);for (int i = 1; i <= n; i ++ ){int x; cin >> x;a[i] = (x & 1);}vector<int> cnt(2);vector<vector<vector<int>>> dp(n + 1, vector<vector<int>>(2, vector<int>(2)));int ans = 0;for (int i = 1; i <= n; i ++ ){for (int j = 0; j < 2; j ++ ){for (int k = 0; k < 2; k ++ ){dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j][k]) % mod;if ((j + k + a[i]) % 2 == 0){dp[i][j][a[i]] = (dp[i][j][a[i]] + dp[i - 1][k][j]) % mod;ans = (ans + dp[i - 1][k][j]) % mod;}}}for (int j = 0; j < 2; j ++ ) dp[i][j][a[i]] = (dp[i][j][a[i]] + cnt[j]) % mod;cnt[a[i]] ++ ;}cout << ans << '\n';
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t = 1;// cin >> t;while (t -- ){solve();}
}

CF 161D Distance in Tree

题目链接

树形dp

做的少数几道树形dp来看,就是存储以每个点为根的子树信息,和 dfs 结合起来做

这一题的 dp[i][j] 就是以 i 为根的子树中,距离为 j 的点的个数

这个值就等于 i 的所有邻接点(除了父结点)的距离为 j - 1 的点数相加

得到这个信息之后,我们就可以计算出当前结点向下走符合条件的点数

还有一种情况是先向上走,走到其他的子树,再向下走

这个情况怎么计算呢?

可以用距离当前结点的父结点为 j - 1 的点数减去距离当前结点为 j - 2的点数,画图很好理解

#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;const int N = 10;
const int mod = 998244353;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;void solve()
{int n, k;cin >> n >> k;vector<vector<int>> g(n + 1);for (int i = 0; i < n - 1; i ++ ){int u, v;cin >> u >> v;g[u].push_back(v);g[v].push_back(u);}vector<vector<int>> dp(n + 1, vector<int>(k + 1));function<void(int, int)> dfs1 = [&](int u, int fa){for (int i = 0; i < g[u].size(); i ++ ){int ver = g[u][i];if (ver == fa) continue;dfs1(ver, u);for (int j = 1; j <= k; j ++ ) dp[u][j] += dp[ver][j - 1];}};for (int i = 1; i <= n; i ++ ) dp[i][0] = 1;dfs1(1, -1);function<void(int, int)> dfs2 = [&](int u, int fa){for (int i = 0; i < g[u].size(); i ++ ){int ver = g[u][i];if (ver == fa) continue;for (int j = k; j >= 1; j -- ) // 因为更新大的需要用到小的 所以从大到小{dp[ver][j] += dp[u][j - 1];if (j > 1) dp[ver][j] -= dp[ver][j - 2];}dfs2(ver, u);}};dfs2(1, -1);int ans = 0;for (int i = 1; i <= n; i ++ ) ans += dp[i][k];cout << ans / 2 << '\n';
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t = 1;// cin >> t;while (t -- ){solve();}
}

CF 1509C The Sports Festival

题目链接

第一次写出来区间dp(虽然很简单!开心ovo

dp[i][j] 就是 [i, j] 内的最佳答案

转移方程: dp[l][r] = min({dp[l][r], dp[l + 1][r] + a[r] - a[l], dp[l][r - 1] + a[r] - a[l]});

#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;const int N = 10;
const int mod = 998244353;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;void solve()
{int n;cin >> n;vector<int> a(n + 1);for (int i = 1; i <= n; i ++ ) cin >> a[i];sort(a.begin() + 1, a.end());vector<vector<int>> dp(n + 1, vector<int>(n + 1, INF));for (int i = 1; i <= n; i ++ ) dp[i][i] = 0;for (int len = 2; len <= n; len ++ ){for (int l = 1; l + len - 1 <= n; l ++ ){int r = l + len - 1;dp[l][r] = min({dp[l][r], dp[l + 1][r] + a[r] - a[l], dp[l][r - 1] + a[r] - a[l]});}}cout << dp[1][n] << '\n';
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t = 1;// cin >> t;while (t -- ){solve();}
}

CF 1398D Colored Rectangles

题目链接

又是dp。。。

以后可以注意一下数据范围,如果比较小的话可以考虑设计一下多维的dp

dp[i][j][k] 表示用 i 个 r ,j 个 g ,k 个 b 的最大面积和

具体怎么更新代码写的很清楚

#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;const int N = 10;
const int mod = 998244353;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;void solve()
{int r, g, b;cin >> r >> g >> b;vector<int> rr(r + 1), gg(g + 1), bb(b + 1);for (int i = 1; i <= r; i ++ ) cin >> rr[i];for (int i = 1; i <= g; i ++ ) cin >> gg[i];for (int i = 1; i <= b; i ++ ) cin >> bb[i];sort(rr.begin() + 1, rr.end());sort(gg.begin() + 1, gg.end());sort(bb.begin() + 1, bb.end());vector<vector<vector<int>>> dp(r + 1, vector<vector<int>>(g + 1, vector<int>(b + 1)));for (int i = 0; i <= r; i ++ ){for (int j = 0; j <= g; j ++ ){for (int k = 0; k <= b; k ++ ){if (i > 0 && j > 0) dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - 1][k] + rr[i] * gg[j]);if (i > 0 && k > 0) dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j][k - 1] + rr[i] * bb[k]);if (j > 0 && k > 0) dp[i][j][k] = max(dp[i][j][k], dp[i][j - 1][k - 1] + gg[j] * bb[k]);}}}cout << dp[r][g][b] << '\n';
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t = 1;// cin >> t;while (t -- ){solve();}
}

相关文章:

  • 排序刷题12 -双向排序
  • Redis之一: 简介及环境安装搭建
  • CNN-LSTM-Attention混合神经网络归时序预测的MATLAB实现(源代码)
  • ESP-VO 论文阅读
  • Fastjson2 <== 2.0.26反序列漏洞
  • redis 为什么会阻塞
  • 二刷代码随想录算法训练营第七天 |454.四数相加II 383. 赎金信 15. 三数之和 18. 四数之和
  • Python 编辑工具 Jupyter notebook
  • PTA天梯 L1-087 机工士姆斯塔迪奥
  • SQL中把datetime 转为字符串
  • 多模态论文阅读--V*指导视觉搜索成为多模态大语言模型的核心机制
  • Java 石头剪刀布小游戏
  • 【MySQL】查询语句:条件、排序和分页
  • Thinkphp框架漏洞--->5.0.23 RCE
  • 通过vue实现左侧树状右侧的组件
  • 《Java8实战》-第四章读书笔记(引入流Stream)
  • 【个人向】《HTTP图解》阅后小结
  • gf框架之分页模块(五) - 自定义分页
  • IndexedDB
  • javascript 哈希表
  • Javascript设计模式学习之Observer(观察者)模式
  • Js实现点击查看全文(类似今日头条、知乎日报效果)
  • maya建模与骨骼动画快速实现人工鱼
  • React-生命周期杂记
  • React中的“虫洞”——Context
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 简析gRPC client 连接管理
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 入口文件开始,分析Vue源码实现
  • 数据科学 第 3 章 11 字符串处理
  • PostgreSQL之连接数修改
  • Spring第一个helloWorld
  • ​你们这样子,耽误我的工作进度怎么办?
  • ​软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】​
  • ###C语言程序设计-----C语言学习(3)#
  • #pragma预处理命令
  • (+4)2.2UML建模图
  • (6)设计一个TimeMap
  • (八)c52学习之旅-中断实验
  • (六)激光线扫描-三维重建
  • (三) diretfbrc详解
  • (数位dp) 算法竞赛入门到进阶 书本题集
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (转) RFS+AutoItLibrary测试web对话框
  • .bat批处理(三):变量声明、设置、拼接、截取
  • .net 4.0 A potentially dangerous Request.Form value was detected from the client 的解决方案
  • .NET Core 将实体类转换为 SQL(ORM 映射)
  • .NET Framework 4.6.2改进了WPF和安全性
  • .net 反编译_.net反编译的相关问题
  • .Net高阶异常处理第二篇~~ dump进阶之MiniDumpWriter
  • .net利用SQLBulkCopy进行数据库之间的大批量数据传递
  • [ 英语 ] 马斯克抱水槽“入主”推特总部中那句 Let that sink in 到底是什么梗?
  • [acwing周赛复盘] 第 69 场周赛20220917
  • [C# 开发技巧]如何使不符合要求的元素等于离它最近的一个元素
  • [C#]使用DlibDotNet人脸检测人脸68特征点识别人脸5特征点识别人脸对齐人脸比对FaceMesh