Loading [MathJax]/extensions/tex2jax.js

AtCoder Grand Contest 035 – 解题报告

A – XOR Circle

考虑对仅有的 \(s \leq 3\) 个元素排列顺序然后判就完事了。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// A.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e5 + 200;
int n, ai[MAX_N], si[MAX_N];
map<int, int> mp, tmp;
int main()
{
scanf("%d", &n);
for (int i = 1, x; i <= n; i++)
scanf("%d", &ai[i]), mp[ai[i]]++;
if (mp.size() <= 3)
{
vector<int> vi;
for (auto x : mp)
vi.push_back(x.first);
bool flag = false;
do
{
int len = vi.size();
tmp.clear();
for (int i = 1; i <= 2; i++)
si[i] = vi[(i - 1) % len];
for (int i = 3; i <= n; i++)
si[i] = si[i - 1] ^ si[i - 2];
for (int i = 1; i <= n; i++)
tmp[si[i]]++;
bool cflag = true;
for (auto x : tmp)
cflag &= mp[x.first] == x.second;
flag |= cflag;
} while (next_permutation(vi.begin(), vi.end()));
puts(flag ? "Yes" : "No");
}
else
puts("No");
return 0;
}
// A.cpp #include <bits/stdc++.h> using namespace std; const int MAX_N = 1e5 + 200; int n, ai[MAX_N], si[MAX_N]; map<int, int> mp, tmp; int main() { scanf("%d", &n); for (int i = 1, x; i <= n; i++) scanf("%d", &ai[i]), mp[ai[i]]++; if (mp.size() <= 3) { vector<int> vi; for (auto x : mp) vi.push_back(x.first); bool flag = false; do { int len = vi.size(); tmp.clear(); for (int i = 1; i <= 2; i++) si[i] = vi[(i - 1) % len]; for (int i = 3; i <= n; i++) si[i] = si[i - 1] ^ si[i - 2]; for (int i = 1; i <= n; i++) tmp[si[i]]++; bool cflag = true; for (auto x : tmp) cflag &= mp[x.first] == x.second; flag |= cflag; } while (next_permutation(vi.begin(), vi.end())); puts(flag ? "Yes" : "No"); } else puts("No"); return 0; }
// A.cpp
#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 1e5 + 200;

int n, ai[MAX_N], si[MAX_N];
map<int, int> mp, tmp;

int main()
{
    scanf("%d", &n);
    for (int i = 1, x; i <= n; i++)
        scanf("%d", &ai[i]), mp[ai[i]]++;
    if (mp.size() <= 3)
    {
        vector<int> vi;
        for (auto x : mp)
            vi.push_back(x.first);
        bool flag = false;
        do
        {
            int len = vi.size();
            tmp.clear();
            for (int i = 1; i <= 2; i++)
                si[i] = vi[(i - 1) % len];
            for (int i = 3; i <= n; i++)
                si[i] = si[i - 1] ^ si[i - 2];
            for (int i = 1; i <= n; i++)
                tmp[si[i]]++;
            bool cflag = true;
            for (auto x : tmp)
                cflag &= mp[x.first] == x.second;
            flag |= cflag;
        } while (next_permutation(vi.begin(), vi.end()));
        puts(flag ? "Yes" : "No");
    }
    else
        puts("No");
    return 0;
}

B – Even Degrees

套路题,首先搞出一个 DFS 树,然后贪心的尝试让本子树合法即可,因为当本子树对子树根的父节点产生影响时,也会存在一个返回父亲的边对其进行调整。当然,调整到根还不行那肯定无解了。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// B.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e5 + 200;
typedef pair<int, int> pii;
int n, m, head[MAX_N], current, parity[MAX_N];
bool inst[MAX_N], vis[MAX_N];
vector<pii> ansBox;
struct edge
{
int to, nxt;
} edges[MAX_N << 1];
void addpath(int src, int dst)
{
edges[current].to = dst, edges[current].nxt = head[src];
head[src] = current++;
}
bool dfs(int u, int fa)
{
vis[u] = inst[u] = true;
for (int i = head[u]; i != -1; i = edges[i].nxt)
if (!vis[edges[i].to] && edges[i].to != fa)
{
bool res = dfs(edges[i].to, u);
parity[u] ^= !res;
if (res)
ansBox.push_back(make_pair(edges[i].to, u));
else
ansBox.push_back(make_pair(u, edges[i].to));
}
inst[u] = false;
for (int i = head[u]; i != -1; i = edges[i].nxt)
if (inst[edges[i].to] && edges[i].to != fa)
if (parity[u])
parity[u] ^= 1, ansBox.push_back(make_pair(u, edges[i].to));
else
parity[edges[i].to] ^= 1, ansBox.push_back(make_pair(edges[i].to, u));
return parity[u];
}
int main()
{
memset(head, -1, sizeof(head));
scanf("%d%d", &n, &m);
for (int i = 1, u, v; i <= m; i++)
scanf("%d%d", &u, &v), addpath(u, v), addpath(v, u);
if (!dfs(1, 0))
for (pii x : ansBox)
printf("%d %d\n", x.first, x.second);
else
puts("-1");
return 0;
}
// B.cpp #include <bits/stdc++.h> using namespace std; const int MAX_N = 1e5 + 200; typedef pair<int, int> pii; int n, m, head[MAX_N], current, parity[MAX_N]; bool inst[MAX_N], vis[MAX_N]; vector<pii> ansBox; struct edge { int to, nxt; } edges[MAX_N << 1]; void addpath(int src, int dst) { edges[current].to = dst, edges[current].nxt = head[src]; head[src] = current++; } bool dfs(int u, int fa) { vis[u] = inst[u] = true; for (int i = head[u]; i != -1; i = edges[i].nxt) if (!vis[edges[i].to] && edges[i].to != fa) { bool res = dfs(edges[i].to, u); parity[u] ^= !res; if (res) ansBox.push_back(make_pair(edges[i].to, u)); else ansBox.push_back(make_pair(u, edges[i].to)); } inst[u] = false; for (int i = head[u]; i != -1; i = edges[i].nxt) if (inst[edges[i].to] && edges[i].to != fa) if (parity[u]) parity[u] ^= 1, ansBox.push_back(make_pair(u, edges[i].to)); else parity[edges[i].to] ^= 1, ansBox.push_back(make_pair(edges[i].to, u)); return parity[u]; } int main() { memset(head, -1, sizeof(head)); scanf("%d%d", &n, &m); for (int i = 1, u, v; i <= m; i++) scanf("%d%d", &u, &v), addpath(u, v), addpath(v, u); if (!dfs(1, 0)) for (pii x : ansBox) printf("%d %d\n", x.first, x.second); else puts("-1"); return 0; }
// B.cpp
#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 1e5 + 200;

typedef pair<int, int> pii;

int n, m, head[MAX_N], current, parity[MAX_N];
bool inst[MAX_N], vis[MAX_N];
vector<pii> ansBox;

struct edge
{
    int to, nxt;
} edges[MAX_N << 1];

void addpath(int src, int dst)
{
    edges[current].to = dst, edges[current].nxt = head[src];
    head[src] = current++;
}

bool dfs(int u, int fa)
{
    vis[u] = inst[u] = true;
    for (int i = head[u]; i != -1; i = edges[i].nxt)
        if (!vis[edges[i].to] && edges[i].to != fa)
        {
            bool res = dfs(edges[i].to, u);
            parity[u] ^= !res;
            if (res)
                ansBox.push_back(make_pair(edges[i].to, u));
            else
                ansBox.push_back(make_pair(u, edges[i].to));
        }
    inst[u] = false;
    for (int i = head[u]; i != -1; i = edges[i].nxt)
        if (inst[edges[i].to] && edges[i].to != fa)
            if (parity[u])
                parity[u] ^= 1, ansBox.push_back(make_pair(u, edges[i].to));
            else
                parity[edges[i].to] ^= 1, ansBox.push_back(make_pair(edges[i].to, u));
    return parity[u];
}

int main()
{
    memset(head, -1, sizeof(head));
    scanf("%d%d", &n, &m);
    for (int i = 1, u, v; i <= m; i++)
        scanf("%d%d", &u, &v), addpath(u, v), addpath(v, u);
    if (!dfs(1, 0))
        for (pii x : ansBox)
            printf("%d %d\n", x.first, x.second);
    else
        puts("-1");
    return 0;
}

C – Skolem XOR Tree

先参考下面的图:

考虑一个 \(2i \oplus (2i + 1) = 1\) 性质,所以可以直接这样去搞。

如果 \(n\) 是偶数的话,就只能搞出来一条半链,所以我们考虑直接枚举整链的接点,强心接上去即可。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// C.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e5 + 200;
int n;
int main()
{
scanf("%d", &n);
if (__builtin_popcount(n) == 1)
puts("No"), exit(0);
puts("Yes"), printf("1 2\n2 3\n3 %d\n%d %d\n%d %d\n", n + 1, n + 1, n + 2, n + 2, n + 3);
for (int i = 4; i < n; i += 2)
printf("1 %d\n%d %d\n1 %d\n%d %d\n", i, i, i + 1 + n, i + 1, i + 1, i + n);
if (!(n & 1))
{
for (int i = 2; i <= n; i++)
{
int u = i ^ n ^ 1;
if (i != 3 && u != 3 && u <= n)
{
printf("%d %d\n%d %d\n", i, n, u, 2 * n);
break;
}
}
}
return 0;
}
// C.cpp #include <bits/stdc++.h> using namespace std; const int MAX_N = 1e5 + 200; int n; int main() { scanf("%d", &n); if (__builtin_popcount(n) == 1) puts("No"), exit(0); puts("Yes"), printf("1 2\n2 3\n3 %d\n%d %d\n%d %d\n", n + 1, n + 1, n + 2, n + 2, n + 3); for (int i = 4; i < n; i += 2) printf("1 %d\n%d %d\n1 %d\n%d %d\n", i, i, i + 1 + n, i + 1, i + 1, i + n); if (!(n & 1)) { for (int i = 2; i <= n; i++) { int u = i ^ n ^ 1; if (i != 3 && u != 3 && u <= n) { printf("%d %d\n%d %d\n", i, n, u, 2 * n); break; } } } return 0; }
// C.cpp
#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 1e5 + 200;

int n;

int main()
{
    scanf("%d", &n);
    if (__builtin_popcount(n) == 1)
        puts("No"), exit(0);
    puts("Yes"), printf("1 2\n2 3\n3 %d\n%d %d\n%d %d\n", n + 1, n + 1, n + 2, n + 2, n + 3);
    for (int i = 4; i < n; i += 2)
        printf("1 %d\n%d %d\n1 %d\n%d %d\n", i, i, i + 1 + n, i + 1, i + 1, i + n);
    if (!(n & 1))
    {
        for (int i = 2; i <= n; i++)
        {
            int u = i ^ n ^ 1;
            if (i != 3 && u != 3 && u <= n)
            {
                printf("%d %d\n%d %d\n", i, n, u, 2 * n);
                break;
            }
        }
    }
    return 0;
}

D – Add and Remove

直接搜。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// D.cpp
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAX_N = 20, INF = 0x3f3f3f3f3f3f3f3f;
int n;
ll ai[MAX_N];
ll solve(int l, int r, ll cL, ll cR)
{
if (l + 1 > r - 1)
return 0;
ll ret = INF;
for (int i = l + 1; i <= r - 1; i++)
ret = min(ret, solve(l, i, cL + cR, cR) + solve(i, r, cL, cL + cR) + 1LL * (cL + cR) * ai[i]);
return ret;
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%lld", &ai[i]);
printf("%lld\n", solve(1, n, 1, 1) + ai[1] + ai[n]);
return 0;
}
// D.cpp #include <bits/stdc++.h> using namespace std; typedef long long ll; const ll MAX_N = 20, INF = 0x3f3f3f3f3f3f3f3f; int n; ll ai[MAX_N]; ll solve(int l, int r, ll cL, ll cR) { if (l + 1 > r - 1) return 0; ll ret = INF; for (int i = l + 1; i <= r - 1; i++) ret = min(ret, solve(l, i, cL + cR, cR) + solve(i, r, cL, cL + cR) + 1LL * (cL + cR) * ai[i]); return ret; } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%lld", &ai[i]); printf("%lld\n", solve(1, n, 1, 1) + ai[1] + ai[n]); return 0; }
// D.cpp
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll MAX_N = 20, INF = 0x3f3f3f3f3f3f3f3f;

int n;
ll ai[MAX_N];

ll solve(int l, int r, ll cL, ll cR)
{
    if (l + 1 > r - 1)
        return 0;
    ll ret = INF;
    for (int i = l + 1; i <= r - 1; i++)
        ret = min(ret, solve(l, i, cL + cR, cR) + solve(i, r, cL, cL + cR) + 1LL * (cL + cR) * ai[i]);
    return ret;
}

int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%lld", &ai[i]);
    printf("%lld\n", solve(1, n, 1, 1) + ai[1] + ai[n]);
    return 0;
}

Leave a Reply

Your email address will not be published. Required fields are marked *