240101 咋提全碳
整理一下我都整了些啥。
有实际用途的是萨卡班甲鱼的勾勾(?)、巨型萨卡班甲鱼,亚克力小盒子,百万英镑的周边(迫真),东北大米草稿纸,苹果家的小镜子。
只有观赏价值的是青蛙、章鱼哥挂件、又一个章鱼哥挂件、章鱼哥超级挂件、莱伊拉和芙莉莲的立牌,abd 的风花节周边和散的透卡。
突然很好奇这么多东西我到时候要怎么搬。
多搬几趟呗。
A. 加法游戏
http://222.180.160.110:1024/contest/4626/problem/1
很厉害的一道 XSC 题,所以我 xsc062 不会做是理所当然的。
好吧开个玩笑。注意到限制次数特别小,但这个其实没起到什么提示作用。
还是有一点的。比如我们假设 \(a_{i+1}\ge 0\),两边同时加 \(a_i\),有 \(a_{i+1}+a_i\ge a_i\)。
我们再假设 \(a_i\le 0\),两边同时加 \(a_{i+1}\),有 \(a_i+a_{i+1}\le a_{i+1}\)。
我们有了一个思路,把整个序列的正负变成一样的,然后按照上面两种方式的任意一种从前往后 / 从后往前执行操作。
任意挑选一个正数使其 \(>20\),只需要自增就可以在 \(5\) 次操作内解决。
然后将这个正数加到所有数上面,所有数就都是正的了(花费 \(n=20\) 次操作)。做操作一得到前缀和(花费 \(n=20\) 次操作)即为答案。
如果一个正数都没有怎么办呢?那就是一个全部为非正的序列,直接做操作二得到后缀和即可。
namespace XSC062 {
using namespace fastIO;
const int maxn = 25;
int n, p, x;
int main() {
read(n);
for (int i = 1; i <= n; ++i) {
read(x);
if (x > 0) p = i;
}
if (p) {
print(2 * n + 4, '\n');
for (int i = 1; i <= 5; ++i)
print(p, ' '), print(p, '\n');
for (int i = 1; i <= n; ++i)
print(i, ' '), print(p, '\n');
for (int i = 2; i <= n; ++i)
print(i, ' '), print(i - 1, '\n');
}
else {
print(n - 1, '\n');
for (int i = n - 1; i; --i)
print(i, ' '), print(i + 1, '\n');
}
return 0;
}
} // namespace XSC062
B. 目标和
http://222.180.160.110:1024/contest/4626/problem/2
虽然说是全谈,但是。
好吧讲一讲实现技巧。把所有字面量全部加上 \(n\times V\),再把所有输入值取绝对值(因为正负无所谓),然后跑每组一正一负两个值的分组背包。
这样看来取绝对值似乎没什么意义?
#define int long long
namespace XSC062 {
using namespace fastIO;
const int maxn = 65;
const int inf = 3e5 + 4;
const int lim = 15e4 + 2;
const int maxm = 3e5 + 7;
int n, m;
int a[maxn];
int f[maxn][maxm];
int abs(int x) { return x >= 0 ? x : -x; }
int main() {
read(n);
for (int i = 1; i <= n; ++i)
read(a[i]), a[i] = abs(a[i]);
read(m), m += lim, f[0][lim] = 1;
for (int i = 1; i <= n; ++i) {
for (int j = 0; j <= inf; ++j) {
if (f[i - 1][j]) {
f[i][j + a[i]] += f[i - 1][j];
f[i][j - a[i]] += f[i - 1][j];
}
}
}
print(f[n][m], '\n');
return 0;
}
} // namespace XSC062
#undef int
C. 0/1 背包问题第 k 优解
http://222.180.160.110:1024/contest/4626/problem/3
就很像有序表的最小和。
\(f_{i,j}\) 表示对于 \(i\) 这个空间占用的 \(j\) 优解,然后因为 \(f_{i,1\sim k}\) 本来就是有序的,所以也没什么额外操作之类的了。
令 \(f_{i,1\sim k}\) 为第一个有序表,\(f_{i-V,1\sim k}+W\) 为第二个有序表,因为这个不是求和,所以用类似归并合并有序数组的方式合并之即可。
—— · EOF · ——
真的什么也不剩啦 😖