Codeforces Round #609 (Div. 1)
Codeforces Round #609 (Div. 1)
A
先保留前 位写出当前的答案。如果合法直接输,如果不合法把前 位数字 重新写
B
将网格图黑白染色,答案是 。可通过二分图匹配或手动构造证明
C
考虑分成两步,1.把这些数移到相邻位置 2.消除逆序对。逆序对数量一定。移到相邻位置可以转化为将空格移动到两边,可以(线段树上)二分找到一个 , 左边的往左移更优,右边的往右移更优,然后维护一下区间和就可以计算了(容斥思想)
D
推导: 阶的强连通竞赛图存在 阶的强连通竞赛子图 —> 对于 做多操作一次 —> 枚举被操作的点,判断是否强连通 证明看这里
如何快速断强连通?不难发现,如果非强连通,缩点后拓扑排序,最后一个 内的点出度最小。那么我们将点按出度排序,若存在 ,前 个的出度之和为 ,说明这 个构成最后一个 且和其他点无法构成 。直接 单次 ,用个桶排就没有 了,总复杂度
下面的是 的 的代码
#include <bits/stdc++.h>
using namespace std;
const int N = 2020;
int n, c[N], id[N], k[N]; char a[N][N];
pair<int, int> p[N], pp[N];
int judge () {
int s = 0;
for (int i = 1; i < n; ++i) {
s += pp[i].first; if (s == i * (i - 1) / 2) return 0;
}
return 1;
}
signed main() {
scanf ("%d", &n);
for (int i = 1; i <= n; ++i) scanf ("%s", a[i] + 1);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j) a[i][j] -= '0';
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j) if (a[i][j]) ++c[j];
for (int i = 1; i <= n; ++i) p[i] = {c[i], i};
sort (p + 1, p + n + 1);
for (int i = 1; i <= n; ++i) id[p[i].second] = i;
memcpy (pp, p, sizeof (p));
if (judge ()) return puts ("0 1"), 0;
if (n <= 6) { // brute
int mx = 1 << n;
int mn = 10000, cc = 0;
for (int i = 0; i < mx; ++i) {
int num = 0;
for (int ii = 1; ii <= n; ++ii)
num += (k[ii] = ((i >> (ii - 1)) & 1)), c[ii] = 0;
if (num > mn) continue;
for (int ii = 1; ii <= n; ++ii)
for (int jj = 1; jj <= n; ++jj)
if (a[ii][jj] ^ k[ii] ^ k[jj]) ++c[jj];
for (int ii = 1; ii <= n; ++ii) pp[ii] = {c[ii], ii};
sort (pp + 1, pp + n + 1);
if (judge ()) {
if (num == mn) ++cc; else mn = num, cc = 1;
}
}
if (mn == 10000) return puts ("-1"), 0;
for (int i = 1; i <= mn; ++i) cc *= i;
return printf ("%d %d\n", mn, cc), 0;
}
int res = 0;
for (int i = 1; i <= n; ++i) { // 枚举翻转点
memcpy (pp, p, sizeof (p));
for (int j = 1; j <= n; ++j)
if (a[i][j]) --pp[id[j]].first, ++pp[id[i]].first;
else --pp[id[i]].first, ++pp[id[j]].first;
sort (pp + 1, pp + n + 1); res += judge ();
}
return printf ("1 %d\n", res), 0;
}
E
对于“边权递增”的条件可以建一张新图:以边为节点,相邻的边之间小的向大的连边。要求的就是这张 上的可达点数量
根据定义,如果是树,直接一遍 简单的求和就是答案。但仙人掌中的环会使答案产生重复。幸运的是,重复的地方只可能是环上的最小边,因为只有它可以往两个方向在环上走。更进一步,只有这个环上最小边往最大边走的两条路径都递增才会重复(两条路径可以在最大值处相交)。那么可以预处理出每个环是否有重复
具体做法:从大到小考虑每条边( 的拓扑序),边权的 是两个端点之和,如果这个环会产生重复且此边为最小就要减去最大边的 (即之后重合的部分)。点权的 值亦在此过程中得出
本文作者:-敲键盘的猫-
本文链接:https://www.cnblogs.com/whx666/p/609-div1.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 数据库服务器 SQL Server 版本升级公告
· C#/.NET/.NET Core技术前沿周刊 | 第 23 期(2025年1.20-1.26)
· 程序员常用高效实用工具推荐,办公效率提升利器!