骗分过样例,暴力出奇迹
我原本以为这是 OI O I 圈子中的一句玩笑话,可是在 2018 2018 年的省选季度中,我发现这种“神奇操作”其实非常常见。
骗分过样例
题目链接:【JSOI2018】绝地反击 fleet
这题的
50
50
分,是明显的
计算几何+二分图匹配
计
算
几
何
+
二
分
图
匹
配
。
有同学不会计算几何,有同学不会二分图匹配,还有同学嫌这样写暴力太麻烦了。
但是,有一个比这种方法简单得多的方法,也能获得
50
50
分,那就是算出:
怎么样?惊不惊喜?意不意外?
(出题人知道后可能要气疯了)
暴力出奇迹
题目链接:【9POI2018】秘密袭击 coat
这题的表算似乎是
拉格朗日插值法+线段树合并+FFT
拉
格
朗
日
插
值
法
+
线
段
树
合
并
+
F
F
T
。
然而,使用
O(nk(n−k))
O
(
n
k
(
n
−
k
)
)
的树形动态规划却可以轻易通过此题,代码如下:
#include <cstdio>
#include <cstring>
typedef unsigned int ui;
const ui maxn = 1670;
const ui maxm = 3333;
const ui mod = 64123;
ui cnt, n, m, a[maxn], x[maxn], dp[maxn][maxn];
ui res, tot, ter[maxm], nxt[maxm], lnk[maxn];
inline void update(ui &x, const ui &y) {
x += y, x -= x >= mod ? mod : 0;
}
void addedge(ui u, ui v) {
ter[++tot] = v;
nxt[tot] = lnk[u];
lnk[u] = tot;
}
void treedp(ui u, ui p) {
if (x[u]) {
for (int i = 1; i < m; i++) {
dp[u][i + 1] = dp[p][i];
}
} else {
for (int i = 1; i <= m; i++) {
dp[u][i] = dp[p][i];
}
}
for (ui v, i = lnk[u]; i; i = nxt[i]) {
v = ter[i];
if (v == p) {
continue;
}
treedp(v, u);
}
for (int i = 1; i <= m; i++) {
update(dp[p][i], dp[u][i]);
}
}
int main() {
scanf("%u %u %*u", &n, &m);
for (ui i = 1; i <= n; i++) {
scanf("%u", a + i);
}
for (ui u, v, i = 1; i < n; i++) {
scanf("%u %u", &u, &v);
addedge(u, v), addedge(v, u);
}
for (ui i = 1; i <= n; i++) {
cnt = 0;
for (int j = 1; j <= n; j++) {
x[j] = (a[i] == a[j] ? i >= j : a[i] < a[j]);
cnt += x[j];
}
if (cnt < m) {
continue;
}
memset(dp, 0, sizeof(dp));
dp[i][1] = 1;
for (ui v, j = lnk[i]; j; j = nxt[j]) {
v = ter[j];
treedp(v, i);
}
update(res, a[i] * dp[i][m] % mod);
}
printf("%u\n", res);
return 0;
}
怎么样?惊不惊喜?意不意外?
(出题人知道后可能要气疯了)
(出题人已经气疯啦!!!)
总结
由此我们可以发现,骗分和暴力是十分重要的,在想不出正解的情况下就应该多多使用这些技巧,以拿到更多的分数。