反思
总结而言:三思而后行,永不言弃
赛前准备
刚换 parse-tool 没有熟悉,比赛的时候因为设置问题出了锅
没有调整好草稿本、桌面布局等
考试前应当适当小憩,但保持思维灵敏度
比赛过程
A 题比较简单,但我在没想清楚时就开始写了,后来才发现我的 flag 设置反了
我在草稿本上列出了 B 题不成立的情况,但在后面的推导中麻证不成立会被后续判断给筛除,于是写的时候没有写这一部分,思路不是很清晰,导致思考后面如何包含浪费很多时间,WA了之后一直查代码原因,没有去思考思路是不是又问题,由于我不知道怎么操作的,在某次调整时把 h, w 直接搞反,检查和调整输入花了20分钟,直接心态爆炸
C 题十分显然,然而我先是快速幂出锅,后是快速乘出锅,最后还有精度的问题,于是一直和答案对不上
D 题性质很明显,然而我题目读错,以为需要不止 3 个集合,然后就死活想不出来
错误一览
k <= log(n) / log(fac[i])
改为k <= log(n) / log(fac[i]) + eps
快速幂漏掉
if (y & 1)
扫描二维码关注公众号,回复: 7401233 查看本文章
题解
1228B - Filling the Grid
注意在考虑竖排的填充时,由于是覆盖填充,每次填充前都必须要检查是否有违反情况
最后统计有多少可填可不填即可
#include <cstdio>
#include <algorithm>
const int mod = (int)1e9 + 7;
const int maxn = 1e3 + 10;
int c[maxn], r[maxn], map[maxn], w, h;
int m[maxn][maxn], v[maxn][maxn];
void qmul(int &x) {
x = (x % mod) * 2 % mod;
}
signed main() {
int ans = 1;
scanf("%d %d", &h, &w);
for (int i = 1; i <= h; ++ i) scanf("%d", &r[i]);
for (int i = 1; i <= w; ++ i) scanf("%d", &c[i]);
for (int i = 1; i <= h; ++ i) {
for (int j = 1; j <= r[i]; ++ j) m[i][j] = 1, v[i][j] = 1;
m[i][r[i] + 1] = 0, v[i][r[i] + 1] = 1;
}
for (int i = 1; i <= w; ++ i) {
for (int j = 1; j <= c[i]; ++ j) {
if (!m[j][i] && v[j][i]) return printf("0"), 0;
m[j][i] = 1, v[j][i] = 1;
}
if (v[c[i] + 1][i] && m[c[i] + 1][i]) return printf("0"), 0;
m[c[i] + 1][i] = 0, v[c[i] + 1][i] = 1;
}
for (int i = 1; i <= h; ++ i) {
for (int j = 1; j <= w; ++ j) {
if (!v[i][j]) qmul(ans);
}
}
printf("%d", ans);
}
1228C - Primes and Multiplication
直接统计每一个底数对答案的贡献,细节在于对范围的思考
复杂度 \(O(x^{0.35}+loglogx⋅log{n})\)
#include <cmath>
#include <cstdio>
#include <algorithm>
const int maxn = 1e6 + 10;
const int modn = 1e9 + 7;
#define int long long
#define eps 1e-5
int p[maxn], n, m, t, c, fac[maxn], ans = 1;
inline void sieve() {
for (int i = 2; i < maxn; ++ i) {
if (!p[i]) p[++t] = i;
for (int j = 1; j <= t && p[j] * i < maxn; ++ j) {
p[p[j] * i] = 1; if (i % p[j] == 0) break;
}
}
}
inline int qpow(int x, int y, int mod) {
int res = 1 % mod; x %= mod;
for (; y; y >>= 1, x = x * x % mod)
if (y & 1) res = res * x % mod;
return res;
}
signed main() {
scanf("%lld %lld", &m, &n); sieve();
for (int i = 1; i <= t; ++ i) {
if (m % p[i] == 0) fac[++c] = p[i];
while (m % p[i] == 0) m /= p[i];
}
if (m != 1) fac[++c] = m;
for (int i = 1; i <= c; ++ i) {
int num = 0;
for (int k = 1; k <= log(n) / log(fac[i]) + eps; ++ k)
num += (int)(n / pow(fac[i], k));
ans = ans * qpow(fac[i], num, modn) % modn;
}
printf("%lld", ans);
}
1228D - Complete Tripartite
若 \(x, y\) 有边直接相连,则记 \([x, y] = 1\) 反之为 \(0\)
易知此图有:若 \([x, y] = 1\),则一定在不同集合;反之,则一定在不同集合
因此我们可以先将不直接相连的点先分到同一组,下面我们只需要验证此分发能否满足 \(\forall x \in v_i, y \in v_j [x, y] = 1\)
显然我们不能对每个点进行搜索判断是否满足,复杂度将达到 \(O(n^2)\)
不难发现,这种情况下 \(m = |v1|⋅|v2|+|v2|⋅|v3|+|v3|⋅|v1|\)