日常训练2025-1-8

日常训练2025-1-8

E小红的双生英雄

https://ac.nowcoder.com/acm/contest/99784/E

思路

读题后跟容易发现是一道分组背包的题,转移也比较简单。有一个做动态规划题的技巧是,如果题目相较于传统的DP题有一些其他的约束条件,则把约束条件写成DP的一个维度就行。

代码

#include <bits/stdc++.h>
typedef std::pair<long long, long long> pll;
typedef std::pair<int, int> pii;
#define INF 0x3f3f3f3f
#define MOD 998244353
using i64 = long long;
const int N = 1e5+5;
void solve(){
int n, C, m;
std::cin >> n >> C >> m;
std::vector<pll> tmp(n+1);
std::vector<bool> st(n+1);
for (int i = 1; i <= n; i++) {
int cost, v;
std::cin >> cost >> v;
tmp[i] = pll(cost, v);
}
std::vector<std::vector<pll>> a;
for (int i = 0; i < m; i++){
int u, v, w;
std::cin >> u >> v >> w;
st[u] = st[v] = true;
a.push_back({tmp[u], tmp[v], {tmp[u].first + tmp[v].first, tmp[u].second + tmp[v].second + w}});
}
for (int i = 1; i <= n; i++){
if (!st[i]) a.push_back({tmp[i]});
}
std::vector<std::vector<i64>> dp(C+1, std::vector<i64>(5));
std::vector<std::vector<i64>> ndp(C+1, std::vector<i64>(5));
for (auto s : a){
ndp = dp;
for (int i = 0; i < s.size(); i++){
auto [cost, atk] = s[i];
int ok = i == 2;
for (int j = C; j >= cost; j--){
for (int k = 4; k >= 1 + ok; k--){
dp[j][k] = std::max(dp[j][k], ndp[j-cost][k-1-ok] + atk);
}
}
}
}
i64 ans = 0;
for (int j = 0; j <= C; j++){
for (int k = 0; k <= 4; k++){
ans = std::max(ans, dp[j][k]);
}
}
std::cout << ans << '\n';
}
signed main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2);
int t = 1, i;
for (i = 0; i < t; i++){
solve();
}
return 0;
}

D.Repeated Sequence

rating:800

https://atcoder.jp/contests/abc384/tasks/abc384_d

思路

思考得到,和为 s 的序列由三部分组成:1.一个后缀,2.若干个完整的循环,3.一个前缀。(特殊情况是,连一个完整的循环都没有)。由数学常识可以知道,后缀+前缀的和为 s % sum。

所以本题就是是否存在一个前缀和后缀的和为 s % sum

可以把原序列向后复制一份。然后然后答案就是一个跨越中点的序列的和为 s % sum。当序列不跨越中点时则刚好是特殊情况的时候。

代码

#include <bits/stdc++.h>
typedef std::pair<long long, long long> pll;
typedef std::pair<int, int> pii;
#define INF 0x3f3f3f3f
#define MOD 998244353
using i64 = long long;
const int N = 1e5+5;
void solve(){
i64 n, s;
std::cin >> n >> s;
i64 sum = 0;
std::vector<i64> v((n+1) * 2);
for (int i = 1; i <= n; i++) {
std::cin >> v[i];
v[i+n] = v[i];
}
std::vector<i64> pre((n+1)*2);
for (int i = 1; i <= n*2; i++){
pre[i] = pre[i-1] + v[i];
}
s %= pre[n];
if (s == 0){
std::cout << "Yes\n";
return;
}
std::set<i64> st;
for (int r = 1; r <= 2*n; r++){
if (st.count(pre[r] - s)){
std::cout << "Yes\n";
return;
}
st.insert(pre[r]);
}
std::cout << "No\n";
}
signed main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2);
int t = 1, i;
for (i = 0; i < t; i++){
solve();
}
return 0;
}

本文作者:califeee

本文链接:https://www.cnblogs.com/califeee/p/18660337

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   califeee  阅读(5)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.