2024.12.19 CW 模拟赛
T1
算法
树形 dp.
思路
由于给定的仇视关系为一棵树, 所以我们可以考虑在这颗树上进行 dp.
考虑设 \(f_{u, i}\) 表示当前枚举到第 \(u\) 个人, ta的烟花从 \(l_i + i\) 开始定制的最小仇视值.
那么就有以下转移方程:
\[f_{u, i} = \min(f_{v, j}\ +\ [l_u + i,\ l_u + i + t_i - 1] \cap [l_v + j,\ l_v + j + t_j - 1])
\]
其中 \(v\) 指 \(u\) 的儿子节点.
#include "iostream"
#include "vector"
using namespace std;
constexpr int N = 1e3 + 10;
#define int long long
int n, m;
int l[N], r[N], t[N];
vector<pair<int, int>> e[N];
void init() {
cin >> n >> m;
for (int i = 1; i <= n; ++i)
cin >> l[i] >> r[i] >> t[i], r[i] = r[i] - t[i] + 1;
for (int i = 1; i <= m; ++i) {
int u, v, w;
cin >> u >> v >> w;
e[u].emplace_back(v, w);
e[v].emplace_back(u, w);
}
}
int f[N][N];
bool vis[N][N];
int deal(int a, int b, int c, int d, int val) { return max(0ll, min(b, d) - max(a, c) + 1) * val; }
int dfs(int u, int fa, int st) {
if (vis[u][st])
return f[u][st];
vis[u][st] = 1;
for (auto [v, w] : e[u]) {
if (v == fa)
continue;
int mn = 5e18;
for (int i = 0; i <= r[v] - l[v]; ++i)
mn = min(mn, dfs(v, u, i) + deal(l[u] + st, l[u] + st + t[u] - 1, l[v] + i, l[v] + i + t[v] - 1, w));
f[u][st] += mn;
}
return f[u][st];
}
void calculate() {
for (int i = 1; i <= n; ++i) {
int mn = 5e18;
for (int j = 0; j <= r[i] - l[i]; ++j)
mn = min(mn, dfs(i, 0, j));
return cout << mn << '\n', void();
}
}
void solve() {
init();
calculate();
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
solve();
return 0;
}
T2
算法
质因数分解.
思路
考虑每一个插入 \(\mathbb{S}\) 的数, 如果该数含有质因子 \(p \notin \mathbb{T}\) 并且次幂不为 3 的倍数, 那么取任意的 \(x\) 都不可能满足条件(因为 \(x\) 的因子只能在 \(\mathbb{T}\) 中取).
接下来将使得 \(S_i \times k = \lambda^3\) 的 \(k\) 全部处理出来, 开一个 \(set\) 记录下来, 查询时直接输出即可.
#pragma GCC optimize("Ofast")
#include "iostream"
#include "cmath"
#include "algorithm"
#include "set"
#include "ext/pb_ds/hash_policy.hpp"
#include "ext/pb_ds/assoc_container.hpp"
using namespace std;
using namespace __gnu_pbds;
constexpr int N = 5e2 + 10;
#define int long long
template <class T>
void read(T &x)
{
x = 0;
char ch = getchar();
while (ch < '0' or ch > '9')
ch = getchar();
while (ch >= '0' and ch <= '9')
x = x * 10 + ch - 48, ch = getchar();
}
void print(int x)
{
if (x > 9)
print(x / 10);
putchar(x % 10 + '0');
}
constexpr int INF = 9223372036854775807;
int n, Q, p[N];
void init()
{
read(n);
for (int i = 1; i <= n; ++i)
read(p[i]);
sort(p + 1, p + n + 1);
read(Q);
}
int qpow(int x, int y)
{
__int128 ret = 1;
for (; y; y >>= 1, x *= x)
{
if (ret > INF)
return 0;
if (y & 1)
ret *= x;
}
if (ret > INF or ret <= 0)
return 0;
return ret;
}
int deal(int x)
{
__int128 ret = 1;
for (int i = 1; p[i] <= x and i <= n; ++i)
if (!(x % p[i]))
{
int tmp = 0;
while (!(x % p[i]))
++tmp, x /= p[i];
if (tmp % 3)
ret *= qpow(p[i], 3 - tmp % 3);
if (ret > INF or ret <= 0)
return 0;
}
return ret;
}
bool check(int x)
{
for (int i = 1; p[i] <= x and i <= n; ++i)
while (!(x % p[i]))
x /= p[i];
int t = round(cbrt(x));
if (t * t * t == x)
return 1;
return 0;
}
gp_hash_table<int, int> t;
struct Node
{
int num, v;
friend bool operator<(Node x, Node y)
{
if (x.v ^ y.v)
return x.v > y.v;
return x.num < y.num;
}
};
set<Node> ans;
void calculate()
{
while (Q--)
{
int op, x;
read(op);
if (op == 1)
{
read(x);
if (check(x))
{
int tmp = deal(x);
if (tmp)
{
if (t[tmp])
ans.erase({tmp, t[tmp]});
++t[tmp];
ans.insert({tmp, t[tmp]});
}
}
}
else if (op == 2)
{
read(x);
int tmp = deal(x);
if (tmp)
{
ans.erase({tmp, t[tmp]});
--t[tmp];
if (tmp)
ans.insert({tmp, t[tmp]});
}
}
else
print(ans.begin()->num), putchar('\n');
}
}
void solve()
{
init();
calculate();
}
signed main()
{
solve();
return 0;
}
T3
算法
博弈论, dp, 线段树.
思路
#include "iostream"
using namespace std;
template <class T>
inline void read(T &x) {
x = 0;
char ch = getchar();
while (ch < '0' or ch > '9')
ch = getchar();
while (ch >= '0' and ch <= '9')
x = x * 10 + ch - 48, ch = getchar();
}
void print(__int128 x) {
if (x < 0)
x = -x, putchar('-');
if (x > 9)
print(x / 10);
putchar(x % 10 + '0');
}
#define int long long
constexpr int N = 5e6 + 10;
constexpr __int128 INF = 1e20;
int n, fst;
__int128 f[N];
int a[N], v1, v2;
int to[N], nxt[N], head[N], idx = 0;
void adde(int u, int v) { to[++idx] = v, nxt[idx] = head[u], head[u] = idx; }
void init() {
idx = 0;
read(n), read(fst);
for (int i = 1; i <= n; ++i)
read(a[i]), head[i] = -1, f[i] = INF;
for (int v = 2; v <= n; ++v) {
int u;
read(u);
adde(u, v);
}
read(v1), read(v2);
}
class Segment_Tree {
protected:
int P;
__int128 tr[N << 2];
public:
void build() {
P = 1;
while (P <= n + 1)
P <<= 1;
for (int i = 1; i <= (n << 2); ++i)
tr[i] = INF;
}
void update(int x, __int128 k) {
tr[x += P] = k;
for (x >>= 1; x; x >>= 1)
tr[x] = min(tr[x << 1], tr[x << 1 | 1]);
}
__int128 query() { return tr[1]; }
} st;
bool flag[N], win[N];
void dfs(int u) {
int cnt = 0;
for (int i = head[u]; ~i; i = nxt[i]) {
int v = to[i];
dfs(v);
cnt += !win[v];
}
if (!cnt)
win[u] = flag[u] = 0;
else
win[u] = 1, flag[u] = (cnt == 1);
}
void deal(int u) {
if (!win[u])
st.update(u, INF);
for (int i = head[u]; ~i; i = nxt[i]) {
int v = to[i];
deal(v);
if (!win[u])
f[u] = min(f[u], f[v]);
else if (flag[u] and !win[v])
f[u] = f[v];
}
if (!win[u]) {
f[u] = min(f[u], (__int128)v1 * a[u] + (__int128)v2 * st.query());
st.update(u, a[u]);
}
}
void calculate() {
st.build();
dfs(1);
if ((fst and !win[1]) or (!fst and win[1]))
return puts("0"), void();
for (int i = 1; i <= n; ++i)
if (!win[i])
st.update(i, a[i]);
deal(1);
if (f[1] == INF)
f[1] = -1;
print(f[1]), putchar('\n');
}
void solve() {
init();
calculate();
}
signed main() {
int T;
read(T);
while (T--)
solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现