2.10 CW 练时记录
前言
把之前的题补了一下, 还可以跟榜走, 太棒啦
\(\rm{B}\)
不好是概率与期望
思路
给定 \(n\) 组 \(T_i, P_i\) , 要求一个顺序 \(a_1, a_2, a_3, \cdots , a_k\) , 使得对应的 \(EP = P_1 + P_2 + \ldots + P_k\) 最大, 相同 \(EP\) 应当使得 \(ET = T_1P_1 + (T_1 + T_2)P_2 + \ldots + (T_1 + T_2 + \ldots + T_k)P_k\) 最小, 输出最优的 \(a\)
不难猜想对于一组 \(EP\) 的最大值, 按照 \(T\) 为第一关键字升序, \(P\) 为第二关键字降序排序之后 \(ET\) 一定最小
考虑这个结论是否正确
反证法, 假设交换上述排序后的一对 \(P\) , 贡献之差是
感觉不太好
或者说我们拆 \(ET\)
那感觉很对啊, 不管了, 大不了最后寄了再说
我们先对于每一组 \(\{T_i, P_i\}\) 排序, 然后这样子选取一定是按顺序选
如果没有不同选择方案相同 \(EP\) , 那么就是一个简单的背包问题, 但是我们还要考虑 \(ET\)
猜测对于排序之后的 \(\{T_i, P_i\}\) , 我们可以有一个贪心策略
这个时候发现时空复杂度剩的很多, 可能可以对状态进行处理, 使其更好转移
考虑这样设计状态
令 \(f_{i, j, W}\) 表示考虑到了第 \(i\) 组, 当前的 \(EP\) 为 \(j\) , 当前使用的 \(T\) 为 \(W\) 时, 最小的 \(ET\) 值
但是时间复杂度爆炸了
不会丢了, 一会再说
好的跟榜, 这题过得人多
主要原因还是懒, 不想开新题
考虑「不同选择方案相同 \(EP\)」时, 怎样才能让 \(ET\) 最小, 加状态被证明是完蛋的
发现要输出具体方案, 于是肯定要记录 \(last\) 回溯
不难想到对于每一种「相同 \(EP\)」, 把所有可能的回溯全部记下来, 最后全部跑一遍看哪种方案的 \(ET\) 最优秀
不好实现啊, 丢了
发现 \(ET\) 可以贪心于是可以直接转移, 下午看正解不浪费时间
\(\rm{D}\)
跟榜
思路
好像就是分拆数?
但是可能要写高精度, \(\rm{qcz}\) 大佬说 \(\textrm{\_\_int128}\) 能过, 试一下
代码
#include <bits/stdc++.h>
const int MAXN = 1520;
__int128 p[2][MAXN];
int now = 0, nxt = 1;
void write(__int128 x)
{
if (x < 0) putchar('-'), x = -x;
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
return;
}
int main()
{
freopen("sweets.in", "r", stdin);
freopen("sweets.out", "w", stdout);
int n, k;
scanf("%d %d", &n, &k);
memset(p, 0, sizeof p);
p[now][0] = 1;
for (int i = 1; i <= k; i++) {
std::swap(now, nxt);
memset(p[now], 0, sizeof p[now]);
for (int j = 1; j <= n; j++) {
if (i > j) continue;
p[now][j] += p[nxt][j - 1] + p[now][j - i];
}
}
write(p[now][n]);
return 0;
}
\(\rm{F}\)
跟榜, 看完这道题差不多可以去补昨天的题
话说昨天 \(\rm{C}\) 确实挺聪明的
发现自己理解是假的
思路
吃饭

浙公网安备 33010602011771号