Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!

Posted heyuhhh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!相关的知识,希望对你有一定的参考价值。

传送门

视频题解

A. Johnny and Ancient Computer

签到。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/5 10:13:34
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ‘ ‘; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ‘ ‘; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
 
void run() {
    ll a, b; cin >> a >> b;
    if (a == b) {
        cout << 0 << ‘
‘;
        return;
    }
    if (a > b) {
        int cnt = 0;
        while (a > b && a % 2 == 0) {
            a >>= 1;
            ++cnt;
        }
        if (a == b) {
            cout << (cnt + 2) / 3 << ‘
‘;
        } else {
            cout << -1 << ‘
‘;
        }
        return;
    }
    if (a < b) {
        int cnt = 0;
        while (a < b) {
            a <<= 1;
            ++cnt;
        }
        if (a == b) {
            cout << (cnt + 2) / 3 << ‘
‘;
        } else {
            cout << -1 << ‘
‘;
        }
    }
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    int T; cin >> T; while(T--)
    run();
    return 0;
}

B. Johnny and His Hobbies

(O(n^2))枚举即可。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/5 10:04:42
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ‘ ‘; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ‘ ‘; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
 
void run() {
    int n; cin >> n;
    vector <int> a(n);
    vector <int> cnt(1024);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        ++cnt[a[i]];
    }
    for (int k = 1; k <= 1023; k++) {
        vector <int> nc = cnt;
        for (int i = 0; i < n; i++) {
            --nc[a[i] ^ k];
        }
        bool ok = true;
        for (int i = 0; i < 1024; i++) {
            if (nc[i] != 0) {
                ok = false;
            }
        }
        if (ok) {
            cout << k << ‘
‘;
            return;
        }
    }
    cout << -1 << ‘
‘;
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    int T; cin >> T; while(T--)
    run();
    return 0;
}

C. Johnny and Another Rating Drop

找规律推导一下即可。发现我们可以每一位单独考虑,只用求出每一位的情况即可。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/5 10:38:37
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ‘ ‘; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ‘ ‘; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
 
void run() {
    ll n; cin >> n;
    ll t = 1;
    ll ans = 0;
    for (int i = 1; i < 64; i++) {
        ans += 1ll * i * ((n + t) / (2ll * t));
        t <<= 1;
    }
    cout << ans << ‘
‘;
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    int T; cin >> T; while(T--)
    run();
    return 0;
}

D. Johnny and Contribution

第一步:读题。
第二步:模拟。
最后的顺序就是从小到大进行安排,然后可以优化一下,对于每个结点找mex的时候反过来,在操作较小的结点时先给当前结点打上标记就行。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/4 23:26:19
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ‘ ‘; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ‘ ‘; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 5e5 + 5;
 
int n, m;
vector <int> G[N], v[N];
int a[N];
 
void run() {
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        int u, v; cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    for (int i = 1; i <= n; i++) {
        int x; cin >> x;
        v[x].push_back(i);
    }
    for (int i = 1; i <= n; i++) {
        a[i] = 1;
    }
    vector <int> ans;
    for (int i = 1; i <= n; i++) {
        for (auto u : v[i]) {
            ans.push_back(u);
            if (a[u] != i) {
                cout << -1 << ‘
‘;
                return;
            }
            for (auto to : G[u]) {
                if (a[to] == i) {
                    ++a[to];
                }
            }
        }   
    }
    for (auto it : ans) cout << it << ‘ ‘;
    cout << ‘
‘;
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

E. Johnny and Grandmaster

  • 从大到小进行贪心,我们先将大的扔在一边,然后用其它的尽量来凑齐,可以证明这样最优。
  • 直观上来感觉就是我们最后只剩下一些较小的数,从小到大的话会剩下一些比较大的数。
  • 因为可能会存在一些进位的情况(看作p进制),但容易发现每位最多进(20)次左右,可以用数组模拟,但实现起来代码比较复杂。
  • 考虑反向思考,从大到小进行拆分,(p^k)可以拆分(p)(p^{k-1},p^2)(p^{k-2})...我们用一些小的对其进行抵消,如果能抵消完说明就凑齐了。
  • (p^t)可能爆long long,注意到最多拆(n)个数出来,否则再怎么都凑不齐,也就是说存在一个上界。那么就很好模拟了。

详见代码:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/5 8:18:48
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ‘ ‘; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ‘ ‘; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5, MOD = 1e9 + 7;
 
int qpow(ll a, ll b) {
    ll res = 1;
    while (b) {
        if (b & 1) res = res * a % MOD;
        a = a * a % MOD;
        b >>= 1;
    }
    return res;
}
 
void run() {
    int n, p; cin >> n >> p;
    vector <int> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    if (p == 1) {
        if (n & 1) {
            cout << 1 << ‘
‘;
        } else {
            cout << 0 << ‘
‘;
        }
        return;   
    }
    sort(all(a));
    vector <int> l, r;
    while (sz(a)) {
        r.push_back(a.back());
        a.pop_back();
        ll A = 1;
        int x = r.back();
        for (int i = sz(a) - 1; i >= 0; i--) {
            l.push_back(a[i]);
            int d = x - a[i];
            x = a[i];
            a.pop_back();
            while (d && A < n) {
                A *= p;
                --d;
            }
            if (d == 0 && --A == 0) {
                break;
            }
        }
    }
    int ans = 0;
    for (auto it : l) {
        ans = (ans + MOD - qpow(p, it)) % MOD;
    }
    for (auto it : r) {
        ans = (ans + qpow(p, it)) % MOD;
    }
    cout << ans << ‘
‘;
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    int T; cin >> T; while(T--)
    run();
    return 0;
}

F. Johnny and Megan‘s Necklace

  • 首先注意到我们可以从大到小枚举答案(k),如果存在一种连接方案,所有边权都不小于(k),那么最终答案为(k)并且可以输出方案。
  • 注意到边权计算方式,当枚举第(k)位时,只用关注后面的位数,如果两个数后面二进制位都相等即可相连。
  • 因为每对相邻结点在路径中必须在一起,考虑将边拆为点,具体可以见视频里面说的。
  • 之后每条边都必须经过一次,并且从一个结点出发能回到原结点,那么跑一个欧拉回路即可。

代码如下:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/5 17:05:23
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ‘ ‘; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ‘ ‘; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 5e5 + 5;
 
void run() {
    int n; cin >> n;
    vector <int> a(n), b(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i] >> b[i];
    }
    for (int k = 20; k >= 0; k--) {
        int t = 1 << k;
        vector <vector <pii>> G(t + n);
        for (int i = 0; i < n; i++) {
            G[a[i] & (t - 1)].push_back(MP(i + t, 2 * i));
            G[i + t].push_back(MP(a[i] & (t - 1), 2 * i));
            G[b[i] & (t - 1)].push_back(MP(i + t, 2 * i + 1));
            G[i + t].push_back(MP(b[i] & (t - 1), 2 * i + 1));
        }
        bool ok = true;
        for (int i = 0; i < t + n; i++) {
            if (sz(G[i]) & 1) {
                ok = false;
                break;
            }
        }
        if (ok == false) continue;
        
        vector <bool> del(2 * n);
        vector <int> ans;
        function <void(int, int)> dfs = [&] (int u, int from) {
            while (sz(G[u])) {
                auto it = G[u].back(); G[u].pop_back();
                int v = it.fi, id = it.se;
                if (!del[id]) {
                    del[id] = true;
                    dfs(v, id);
                }
            }
            if (from != -1) ans.push_back(from);
        };   
        
        ans.clear();
        for (int i = 0; i < n + t; i++) {
            if (sz(G[i])) {
                dfs(i, -1);
                break;
            }
        }
        if (sz(ans) < 2 * n) {
            continue;
        }
        cout << k << ‘
‘;
        for (auto it : ans) {
            cout << it + 1 << ‘ ‘;   
        }
        cout << ‘
‘;
        break;
    }
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}


以上是关于Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!

Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!

Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!

Codeforces Round #647 (Div. 2) B. Johnny and His Hobbies(枚举)

Codeforces Round #647 (Div. 2) B. Johnny and His Hobbies(枚举)

Codeforces Round #647 (Div. 2) D. Johnny and Contribution(BFS)