Codeforces Round 919 (Div. 2)
https://codeforces.com/contest/1920
B还行,C、E good(E据说是很典的dp但我是dp苦手),D、F1无聊,F2不会
A. Satisfying Constraints *800
有 个条件,每个条件形如 或 , 为整数。问满足条件的整数 的个数。
先处理 ,得到限制区间的交集,最后把区间中 的减去。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void sol() {
int n;
cin >> n;
int l = -1e9, r = 1e9;
vector<int> neq;
while (n--) {
int t, x;
cin >> t >> x;
if (t == 1) l = max(l, x);
else if (t == 2) r = min(r, x);
else neq.push_back(x);
}
int ans = max(0, r - l + 1);
for (int x : neq) ans -= x >= l && x <= r;
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int T; cin >> T; while (T--)
sol();
}
B. Summation Game *1100
给定正整数数组。Alice先移除不超过 个数,然后Bob把不超过 个数取成相反数,然后游戏结束。Alice想最大化所有数的和 ,Bob想最小化 ,问 最后会是多少。
Bob肯定会取前 大的数,为了减少损失,Alice也得移除最大的若干个数(不一定要移除 个)。从大到小排序数组,枚举Alice移除了几个数,前缀和算算答案即可。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void sol() {
int n, k, x;
cin >> n >> k >> x;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++)
cin >> a[i];
sort(next(a.begin()), a.end(), greater<int>());
for (int i = 1; i <= n; i++)
a[i] += a[i - 1];
int ans = -1e9;
for (int i = 0; i <= k; i++) {
int j = min(n, i + x);
ans = max(ans, -a[j] + a[i] + a[n] - a[j]);
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int T; cin >> T; while (T--)
sol();
}
C. Partitioning the Array *1600 暴露智商了,没做出来555
给定长度为 的数组,对 的每个因子 ,把数组分成 个长度为 的连续子列,若存在 使得每个连续子列在 意义下完全相同,则答案加一。问答案是多少。
转化成 ,,使得
也就是
也就是
取这些数的 即可,也就是
检查 是否为 就行。,注意减法可能出现负数。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int P = 998244353;
void sol() {
int n;
cin >> n;
vector<int> a(n);
for (int &x : a) cin >> x;
vector<int> divs;
for (int i = 1; i <= n / i; i++) {
if (n % i) continue;
divs.push_back(i);
if (i != n / i) divs.push_back(n / i);
}
int ans = 0;
for (int d : divs) {
int g = 0;
for (int i = 0; i < d; i++)
for (int j = i; j < n; j += d)
g = __gcd(g, a[j] - a[i]);
if (g != 1 && g != -1) ans++; //可能负数
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int T; cin >> T; while (T--)
sol();
}
D. Array Repetition *1900 模拟
开始数组为空,两种操作:在末尾添一个数、把整个数组复制 次到末尾。 次询问某个位置 上的数是什么。
模拟。注意越界处理,别爆longlong。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void sol() {
int n, q;
cin >> n >> q;
map<ll, ll> mp;
ll idx = 0;
vector<ll> pos;
for (int i = 0, f = 0; i < n; i++) {
ll t, x;
cin >> t >> x;
if (f) continue;
if (t == 1) {
pos.push_back(++idx);
mp[idx] = x;
} else {
if (idx > (ll)1e18 / (x + 1)) {
f = true;
continue;
}
idx *= x + 1;
}
}
while (q--) {
ll k;
cin >> k;
ll ans = mp[k];
while (!ans) {
ll las = *prev(upper_bound(pos.begin(), pos.end(), k));
k = (k - 1) % las + 1;
ans = mp[k];
}
cout << ans << ' ';
}
cout << '\n';
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int T; cin >> T; while (T--)
sol();
}
E. Counting Binary Strings *2100 得加练dp了
定义“好串”:只有一个 的 串。
问恰有 个好子串且所有好子串的长度 的 串数量。
形如 000100000 的子串对答案的贡献为 ,其中 分别为左右两边 的数量。
dp。 表示有 个好子串,最后一段 的长度为 的串的数量。( 和总串长完全不用管)
枚举最后一段 的数量 ,则
注意初值
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int P = 998244353;
void sol() {
ll n, K;
cin >> n >> K;
vector f(n + 1, vector<ll>(K));
fill(f[0].begin(), f[0].end(), 1);
for (int i = 1; i <= n; i++) {
for (int j = 0; j < K; j++) {
for (int k = 0; j + k + 1 <= K && i - (j + 1) * (k + 1) >= 0; k++) {
(f[i][j] += f[i - (j + 1) * (k + 1)][k]) %= P;
}
}
}
cout << accumulate(f[n].begin(), f[n].end(), 0ll) % P << '\n';
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int T; cin >> T; while (T--)
sol();
}
F1. Smooth Sailing (Easy Version) *2500 好想难写的简单二分答案+bfs
给定图,每个点是海底火山/岛屿/海洋。岛屿是个四连通区域且不与边界接壤,火山和海洋都能行船。
环岛路线:由非岛屿点组成,环绕所有岛屿,使岛屿与边界不能八连通。
环岛路线的安全度:路线中每个点到每座火山的曼哈顿距离的最小值。
次询问,问从某点出发的环岛路线的安全度最大是多少。
二分答案 ,把起点所在的安全度 的非岛屿四连通区域标出,看这个区域能把不能把岛屿的边界包含在内
也就是把上述区域ban掉,看边界与岛屿是否八连通即可。代码很长
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int dx[] = {0,0,1,-1,1,-1,-1,1};
const int dy[] = {1,-1,0,0,1,1,-1,-1};
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int n, m, q;
cin >> n >> m >> q;
vector g(n + 1, vector<char>(m + 1));
queue<pair<int, int>> que;
vector dis(n + 1, vector<int>(m + 1, -1));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> g[i][j];
if (g[i][j] == 'v') {
que.push({i, j});
dis[i][j] = 0;
}
}
}
while (!que.empty()) { //计算每个点到最近火山的曼哈顿距离
auto [x, y] = que.front(); que.pop();
for (int i = 0; i < 4; i++) {
int xx = x + dx[i], yy = y + dy[i];
if (xx < 1 || xx > n || yy < 1 || yy > m) continue;
if (dis[xx][yy] != -1) continue;
dis[xx][yy] = dis[x][y] + 1;
que.push({xx, yy});
}
}
while (q--) {
int x, y;
cin >> x >> y;
auto ok = [&](int mid) {
if (dis[x][y] < mid) return false;
vector f(n + 1, vector<int>(m + 1)); //f=1与(x,y)四连通,f=2与边界八连通
f[x][y] = 1;
queue<pair<int, int>> q;
q.push({x, y});
while (!q.empty()) {
auto [x, y] = q.front(); q.pop();
for (int i = 0; i < 4; i++) {
int xx = x + dx[i], yy = y + dy[i];
if (xx < 1 || xx > n || yy < 1 || yy > m) continue;
if (f[xx][yy] || dis[xx][yy] < mid || g[xx][yy] == '#') continue;
f[xx][yy] = 1;
q.push({xx, yy});
}
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if ((i == 1 || i == n || j == 1 || j == m) && !f[i][j])
q.push({i, j}), f[i][j] = 2;
while (!q.empty()) {
auto [x, y] = q.front(); q.pop();
for (int i = 0; i < 8; i++) {
int xx = x + dx[i], yy = y + dy[i];
if (xx < 1 || xx > n || yy < 1 || yy > m) continue;
if (g[xx][yy] == '#') return false;
if (f[xx][yy]) continue;
f[xx][yy] = 2;
q.push({xx, yy});
}
}
return true;
};
int l = 0, r = 2e5, ans = 0;
while (l <= r) {
int mid = l + r >> 1;
if (ok(mid)) ans = mid, l = mid + 1;
else r = mid - 1;
}
cout << ans << '\n';
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2022-02-08 cf279 E. Beautiful Decomposition(贪心)