2021.5.14 模拟赛游记
次阅读
4 min read
恐怕又变成严重事故征候调查报告了。
本来是想着一定要吸取上次的教训严格执行检查单和标操作程序的,虽然最后一题差了那么一些但前两题总应该过的吧。
结果吃好午饭回来就是事故现场了。
A
签到题。
B
同样很容易想到直接用树状数组的做法,但我一时脑抽还加了个 set
, 本来也是没有问题的,结果就直接炸成 分了。
KTSB 第一时间就展开了调查。 数据扔进去一看,居然是用空格分隔的,我怎么用了换行符呢?改了之后还是 分,盯着看了很久没有发现任何问题,结果老板看了一眼就说:“没有取模”。
居然还真是没有取模。
没有取模。
取模。
取模可是在检查单里的啊!代码注释下面就写了 mod
居然会死在取模上。
IO
似乎也是在检查单上的。
C
执行 次,每次在 的网格上随机选俩点,求 次之后覆盖的格子大小的期望。
开始就是直接想的,模拟了一下小样例,然后试图发现一些性质,然后就发现了这条路是走不通的,因为不同的形态太多了。
此时已经是最后半小时了吧,想着换一种思路来考虑这个问题,于是考虑每一个点对答案的贡献,设所有方案的总数是 , 包含当前点的方案是 个, 那么一次取到的概率 就是 , 那么 次里面有至少一个取到的方案数是多少呢?
我居然傻乎乎的想当然了一下认为是 , 显然是 啊!然后就考虑 怎么求。
开始的时候想的是只考虑左上和右下的,总方案数也除以个 ,结果搞了半天没有搞出来,比赛就结束了。
其实左下和右上同样构成答案,这里不像其它一些问题中是可以省略的。那么来考虑怎么样不会有重复。介于我容斥啥一窍不通,所以就直接分成九块大力讨论了,然后代码就变成这个样子了:
#include <cstdio>
#include <cmath>
int n, k, m;
double ans, p;
int main() {
freopen("paint.in", "r", stdin);
freopen("paint.out", "w", stdout);
scanf("%d%d%d", &k, &n, &m);
double w = (double)n*m*n*m;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) {
double s1 = (i-1)*(j-1),
s2 = i-1,
s3 = (m-j)*(i-1),
s4 = j-1,
s5 = m-j,
s6 = (j-1)*(n-i),
s7 = n-i,
s8 = (m-j)*(n-i);
double t = s1 * (s5 + s7 + s8 + 1)
+ s2 * (s4 + 1 + s5 + s6 + s7 + s8)
+ s3 * (s4 + 1 + s7 + s6)
+ s4 * (s2 + s3 + 1 + s5 + s7 + s8)
+ s5 * (s1 + s2 + s4 + 1 + s6 + s7)
+ s6 * (s2 + 1 + s3 + s5)
+ s7 * (s1 + s2 + s3 + s4 + 1 + s5)
+ s8 * (s1 + s2 + s4 + 1)
+ 1 + s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8;
t /= w;
p = t;
ans += (1 - pow(1-p, k));
}
printf("%.8lf", ans);
return 0;
}
结论和建议
想着 “严格执行检查单和标操作程序的”, 结果还是因为没有真正做好这些要求而失去了 B 的 分。
至于 C,则是 机械故障 技术上的错误了。
所以:
- 要认真执行检查单。
- 输入输出条目不仅包括文件,也得包括输出格式。
- 检查取模不能停留在表面,必须检查每一个需要取模的运算。
- 不能想着以后对拍,必须及时执行
test
项。
- 数学问题不能只想当然。
- "至少取到一个" 的问题刻意转换成“一个都不取到”然后容斥一下。
- 遇到重复时静下来暴力讨论也是个好方法。