AtCoder Grand Contest 039
Posted lyfoi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Grand Contest 039相关的知识,希望对你有一定的参考价值。
A Connection and Disconnection
Description
将一个由小写字母构成字符串 \(S\) 复制 \(k\) 遍得到 \(T\),可以将 \(T\) 中的字母更换为任意一个字母,求至少在 \(T\) 中更换几个字母才能没有两个相邻的相同的字母。
Solution
对于字符串 \(T\),它的相邻相同字母分成两个情况,一个是 \(S\) 内部,一个是复制 \(S\),在两个 \(S\) 的相交。若没有相交的贡献非常简单,两个相邻相同的字符将右边的字符换掉即可。如果有相交贡献,即为 \(S\) 的最后一个字符与他开头的字符相同,那么分两种情况。一种是 \(S\) 的末尾已经被更换了,一定能让 \(S\) 的末尾更换的字母与 \(S\) 开头的不同,另一种是 \(S\) 的末尾没有被更换,那么要在与它相交的 \(S\) 的开头更换。如果一个 \(S\) 的开头被更换了,那么它的贡献是 \(1\),否则为 \(0\)。
现在可以写暴力了,但是可以发现内部的贡献是一样的,而相交的贡献为 \(0\) 或 \(1\),可以发现,所有 \(S\) 的相交贡献的可能有 \(3\) 种情况,一种是贡献都为 \(1\),另一种是贡献都为 \(0\),还有一种是 \(0\) 与 \(1\) 交替。我们可以尝试前两个数把规律找出来,然后用公式求。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int read()
int x = 0, f = 0; char ch = 0;
while (!isdigit(ch)) f |= ch == '-', ch = getchar();
while (isdigit(ch)) x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
return f ? -x : x;
bool f;
int get(string s)
int ans = 0;
if (f) ans++, s[0] = '#';
for (int i = 1; i < s.size(); i++)
if (s[i] == s[i - 1]) ans++, s[i] = '#';
if (s[s.size() - 1] == s[0] && s[s.size() - 1] != '#') f = 1;
if (s[s.size() - 1] == '#') f = 0;
return ans;
int main()
string s; cin >> s; int k = read();
ll ans = get(s);
if (f)
int nxt = get(s);
if (f) ans += 1ll * nxt * (k - 1);
else ans += 1ll * nxt * (k - 1 - k / 2) + 1ll * ans * k / 2;
else ans += 1ll * (k - 1) * get(s);
printf("%lld\n", ans);
return 0;
B Graph Partition
Description
将一张无向图染色,相邻节点颜色相邻,求最多能染多少颜色。如果没有方案输出 \(-1\)。
Solution
先考虑无解的情况,如果有一个奇环,那么颜色相邻就自相矛盾了,所以先特判掉。然后贪心的考虑,只要让最长的一条路径每条边的颜色不同就可以了,其他的边可以不顾一切的为最长路径上的边牺牲,所以答案是所有两点最短路的最大值 \(+1\)。
Code
#include <bits/stdc++.h>
using namespace std;
const int N = 500 + 5, INF = 0x3f3f3f3f;
int read()
int x = 0, f = 0; char ch = 0;
while (!isdigit(ch)) f |= ch == '-', ch = getchar();
while (isdigit(ch)) x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
return f ? -x : x;
int a[N][N];
int main()
int n = read();
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
char c; scanf(" %c", &c); a[i][j] = c - '0';
if (!a[i][j] && i != j) a[i][j] = INF;
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
a[i][j] = min(a[i][j], a[i][k] + a[k][j]);
int ans = -INF;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if ((a[i][j] & 1 == 0 && (a[1][i] & 1) != (a[1][j] & 1) || (a[i][j] & 1 && (a[1][i] & 1) == (a[1][j] & 1))))
puts("-1");
return 0;
ans = max(ans, a[i][j]);
printf("%d\n", ans + 1);
return 0;
咕咕。
以上是关于AtCoder Grand Contest 039的主要内容,如果未能解决你的问题,请参考以下文章
Atcoder Grand Contest 039B(思维,BFS)
Atcoder Grand Contest 039C(容斥原理,计数DP)