2021.5.14 模拟赛游记

恐怕又变成严重事故征候调查报告了。

本来是想着一定要吸取上次的教训严格执行检查单和标操作程序的,虽然最后一题差了那么一些但前两题总应该过的吧。

结果吃好午饭回来就是事故现场了。

A

签到题。

B

同样很容易想到直接用树状数组的做法,但我一时脑抽还加了个 set, 本来也是没有问题的,结果就直接炸成 00 分了。

KTSB 第一时间就展开了调查。 数据扔进去一看,居然是用空格分隔的,我怎么用了换行符呢?改了之后还是 4040 分,盯着看了很久没有发现任何问题,结果老板看了一眼就说:“没有取模”。

居然还真是没有取模。

没有取模。

取模。

取模可是在检查单里的啊!代码注释下面就写了 mod 居然会死在取模上。

IO 似乎也是在检查单上的。

C

执行 kk 次,每次在 n×mn\times m 的网格上随机选俩点,求 kk 次之后覆盖的格子大小的期望。

开始就是直接想的,模拟了一下小样例,然后试图发现一些性质,然后就发现了这条路是走不通的,因为不同的形态太多了。

此时已经是最后半小时了吧,想着换一种思路来考虑这个问题,于是考虑每一个点对答案的贡献,设所有方案的总数是 ww, 包含当前点的方案是 tt 个, 那么一次取到的概率 pp 就是 tw\frac{t}{w}, 那么 kk 次里面有至少一个取到的方案数是多少呢?

我居然傻乎乎的想当然了一下认为是 3p3p, 显然是 (1(1p)k)(1-(1-p)^k) 啊!然后就考虑 tt 怎么求。

开始的时候想的是只考虑左上和右下的,总方案数也除以个 44,结果搞了半天没有搞出来,比赛就结束了。

其实左下和右上同样构成答案,这里不像其它一些问题中是可以省略的。那么来考虑怎么样不会有重复。介于我容斥啥一窍不通,所以就直接分成九块大力讨论了,然后代码就变成这个样子了:

#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 的 100100 分。

至于 C,则是 机械故障 技术上的错误了。

所以:

  1. 要认真执行检查单。
    1. 输入输出条目不仅包括文件,也得包括输出格式。
    2. 检查取模不能停留在表面,必须检查每一个需要取模的运算。
    3. 不能想着以后对拍,必须及时执行 test 项。
  2. 数学问题不能只想当然。
    1. "至少取到一个" 的问题刻意转换成“一个都不取到”然后容斥一下。
    2. 遇到重复时静下来暴力讨论也是个好方法。