日常训练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;
}
posted @ 2025-01-08 18:28  califeee  阅读(22)  评论(0)    收藏  举报