【周考】Round1 2024.7.6
Summary
Score: \(100+90+0+50+4=244\)
T1 减法操作
Algorithm: 思维
考虑对 \(n\) 分奇偶讨论:
- 偶数:显然 最小质因子 为 \(2\),而每次减 \(2\) 后仍是偶数。所以偶数一定进行了 \(\dfrac n 2\) 次操作;
- 奇数:因为是奇数,所以 最小质因子 一定也是奇数,减去后则变为偶数,接着可以转化为偶数处理。
时间复杂度:\(O(\sqrt n)\)
code
#include <cstdio>
long long n, ans;
int main () {
scanf("%lld", &n);
if (n & 1) {
for (long long i = 3; i * i <= n; i++)
if (!(n % i))
return printf("%lld", 1 + (n - i) / 2), 0;
ans = 1;
} else
ans = n / 2;
printf("%lld", ans);
return 0;
}
T2 匹配数
Algorithm: 爆搜 / DP
考场思路:
感觉直接爆搜的时间复杂度实在是玄学,一下子想到了 贪心 (为什么不是 DP。。。
虽然考场上,对于 \(n=10\) 的数据,拍了 \(114514\) 多组(真,但是最后还是
WA
了 \(90\text{pts}\)。设最终答案数组为 \(a\),对于 \(a[i]\),从贪心的角度分类讨论:
- 对于
<
:\(a[i]=a[i-1]+1\);- 对于
>
:
- 若 \(a[i-1]\neq 0\) :\(a[i]=0\);
- 若 \(a[i-1]=0\) :从 \(i\) 往前,直到第一个不等号的 \(a\) 都自加 \(1\)(当然还有很多细节,比如不等于的处理;
- 对于
!
:
- 若 \(a[i-1]\neq 0\) :\(a[i]=0\);
- 若 \(a[i-1]=0\) :\(a[i]=1\);
- 对于
=
:\(a[i]=a[i-1]\)。时间复杂度:\(O(nm)\)。其中 \(m\) 为
>
的数量。code for 贪心(90pts
#include <cstdio> #include <cstring> const int MAXN = 2005; char s[MAXN]; int n, l, a[MAXN]; int main () { scanf("%s", s + 1), n = strlen(s + 1); a[0] = 1; for (int i = 1; i <= n; i++) { if (s[i] == '>') { a[i] = 0; if (a[i - 1] == 0) { for (int j = i - 1; j >= 0; j--) { a[j]++; if (s[j] == '!') { if (a[j] == a[j - 1]) { a[j]++; for (int k = j + 1; k <= i; k++) { if (s[k] == '=' || s[k] == '<') { a[k]++; } else if (s[k] == '!') { //根本就不可能。。。 } else break; } } break; } if (s[j] == '<' && a[j - 1] < a[j]) break; if (s[j] == '>' && a[j - 1] > a[j]) break; } } } if (s[i] == '<') { a[i] = a[i - 1] + 1; } if (s[i] == '=') { a[i] = a[i - 1]; } if (s[i] == '!') { if (a[i - 1] == 0) a[i] = 1; else a[i] = 0; } } for (int i = 0; i <= n; i++) putchar(a[i] + '0'); return 0; } /* Hacks: <>!=<>!=<>!=<>!=<>!= 120112011201120112011 =!!!> 110120 ==>>> 333210 ><!=> 101220 <>>=> 132110 <<<<<<<<><<<<<<<<><<<<<<<<><<<<<<<<! */
爆搜
记录当前位填充的可能性(数字范围 & 不能取的值)
对于最后一位直接枚举输出即可,不需要在递归时对后一位进一步限制。
时间复杂度:\(O(\text{玄学})\),但是由于是从最小的开始搜,实际上是肯定跑不满的。
code
#include <cstdio>
#include <cstring>
#include <algorithm>
const int MAXN = 2005;
char s[MAXN];
int n, a[MAXN];
void dfs (int now, int l, int r, int no) {
if (now > n) {
for (int i = 0; i <= n; i++) putchar(a[i] + '0'); puts("");
std::exit(0);
}
if (now == n) {
for (int i = l; i <= r; i++) if (i != no) {
a[now] = i;
dfs(now + 1, 0, i - 1, -1);
}
}
for (int i = l; i <= r; i++) if (i != no) {
a[now] = i;
if (s[now] == '>') dfs(now + 1, 0, i - 1, -1);
if (s[now] == '<') dfs(now + 1, i + 1, 9, -1);
if (s[now] == '!') dfs(now + 1, 0, 9, i);
if (s[now] == '=') dfs(now + 1, i, i, -1);
}
}
int main () {
scanf("%s", s), n = strlen(s);
dfs(0, 1, 9, -1);
return 0;
}
T3 染色
将颜色相同的一段子区间称做「一段」
则至少 \(N-K\) 段,才能使多出来的 \(K-1\) 个格子即使放在一起也只有 \(K\) 对相邻的格子。
考虑满足「满足相邻的同色格子 恰为 \(K\) 对」 的方案数。
不考虑染色,则有