CF2090 A-F1
赛时只做了 A-D,赛后看了家乐的码把剩下的题改了
比较 \(a\bmod (x+y)\) 与 \(x\) 的大小即可
时间复杂度:\(O(1)\)
cin >> x >> y >> a, t = x + y, a %= t;
pr(a >= x);
一个点一定是从右往左或从上往下堆起来的,那么如果右边或下面有空格则一定无解。否则一定可以找出一种可行解
时间复杂度:\(O(n^3)\)(假定 \(n,m\) 同阶)
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> ch, a[i][j] = ch - '0';
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (a[i][j] == 1) {
bool F = 1, G = 1;
for (int k = 1; k < i; k++) {
F &= a[k][j];
}
for (int k = 1; k < j; k++) {
G &= a[i][k];
}
ans &= (F || G);
}
}
}
pr(ans);
考虑让连续一段的 \(c_i\) 是同一个数,找到最大的质数 \(k\) 使得 \(2k \le n\),那么在 \(p_{1\sim 2k}\) 中直接最小最大交替放。就可以最大化 \(c_i=k\) 的个数,剩下的数直接 \(p_i=i\) 即可
时间复杂度:\(O(n)\)
cin >> n, ans = n / 3 - 1;
for (int i = n; i; i--) {
if (!vis[i / 2]) {
lim = i / 2;
break;
}
}
for (int i = 1; i <= lim; i++) {
a[i * 2 - 1] = b[i], a[i * 2] = b[lim * 2 - i];
}
for (int i = lim * 2; i <= n; i++) {
a[i] = i;
}
int cnt = 0, t = 0;
for (int i = 1; i <= n; i++) {
cnt += a[i];
t += !vis[(cnt + i - 1) / i];
cout << a[i] << " \n"[i == n];
}
E1 和 E2 基本一样,\(-1\) 的操作进行的时间不重要,于是可以计算 \(\sum a_i\),在操作的过程中将 \(\text{sum}\) 同时减去,当 \(\text{sum}\le k\) 时直接输出答案
用两个 set 存下两个数组中非零的数,每一轮对于 a 中的数在 b 中 lower_bound,如果找到了则直接对应删除
时间复杂度:\(O(n\log n)\)
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i], sum += a[i], a[i] && (s[0].insert(i), 0);
}
for (int i = 1; i <= n; i++) {
cin >> b[i], b[i] && (s[1].insert(i), 0);
}
for (int i = 0; i <= n + 2; i++) {
if (sum <= k) {
cout << i << '\n';
break;
}
tmp.clear();
for (auto L = s[0].begin(), R = s[1].begin(); !s[0].empty();) {
L == s[0].end() && (L = s[0].begin(), 0);
if (tmp.count(*L)) {
break;
}
tmp.insert(*L), R = s[1].lower_bound(((*L + i - 1) % n) + 1);
if (R == s[1].end() || *R != ((*L + i - 1) % n) + 1) {
if (s[1].empty()) {
break;
}
R == s[1].end() && (R = s[1].begin(), 0), L = s[0].lower_bound(((*R + n - i - 1) % n) + 1);
} else {
o = min(a[*L], b[*R]), a[*L] -= o, b[*R] -= o, sum -= o;
if (!a[*L]) {
L = s[0].erase(L), !b[*R] && (R = s[1].erase(R), 0);
} else {
R = s[1].erase(R);
if (s[1].empty()) {
break;
}
R == s[1].end() && (R = s[1].begin(), 0), L = s[0].lower_bound(((*R + n - i - 1) % n) + 1);
}
}
}
}
F1. Key of Like (Easy Version)
枚举每一轮钥匙的选择,根据小学奥数知识,在剩下 \(k\) 把锁时接下来 \(k\) 个人开锁成功的概率都是 \(\frac{1}{k}\),但是需要考虑 \(k>n\) 的情况,那么有些人的概率会增加,但解决方法直接向 \(n\) 取模即可。但是需要用树状数组维护概率的差分来计算
时间复杂度:\(O(nk\log^2 n)\)
cin >> n >> k >> Joler_Is_SB, v[n] = 1, tr.sz = k + n << 2;
for (int i = k; i; i--) {
for (int j = 1; j <= n; j++) {
tr.update(j + 1, v[j] * P(i, kP - 2) % kP), tr.update(j + i + 1, kP - (v[j] * P(i, kP - 2) % kP));
}
fill(v, v + n + 2, 0);
for (int j = 1; j <= n; j++) {
for (int l = j; l <= n + k + 1; l += n) {
(v[j] += tr.query(l)) %= kP;
}
(ans[j] += v[j]) %= kP;
}
tr.init();
}
for (int i = 1; i <= n; i++) {
cout << ans[i] << " \n"[i == n];
}
家乐也不会 F2,哈哈哈哈哈哈哈

浙公网安备 33010602011771号