题解 | #2023牛客暑期多校训练营3#

World Fragments I

https://ac.nowcoder.com/acm/contest/57357/A

Link

A

C++ Code
#include "bits/stdc++.h"

using namespace std;
using i64 = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    string s, t;
    cin >> s >> t;
    i64 x = 0, y = 0;
    for (auto &si : s) {
        x = x * 2 + si - '0';
    }
    for (auto &ti : t) {
        y = y * 2 + ti - '0';
    }
    if (x == 0 && y != x) {
        cout << "-1\n";
    } else {
        cout << abs(x - y) << '\n';
    }
    
    return 0;
}

D

变成全 或全

C++ Code
#include "bits/stdc++.h"

using namespace std;
using i64 = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin >> n;
    vector<string> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }

    string s;
    int c0 = 0, c1 = 0;
    for (int i = 0; i < n; i++) {
        s += a[0][i] ^ 1;
        c0 += (a[0][i] == '0');
        c1 += (a[i][0] == '0');
    }

    for (int i = 0; i < n; i++) {
        if (a[i] != s && a[i] != a[0]) {
            cout << "-1\n";
            return 0;
        }
    }
    cout << min(n - c1, c1) + min(n - c0, c0) << '\n';
    
    return 0;
}

E

为从 途中所能经过的最多边(到达 就停下来), 为从 的最短路,若 则 Yes。

G

可以二分 ,枚举每个点作为靠近对称点的点算出对应的最大中心对称正方形(边长分奇偶),

C++ Code
#include "bits/stdc++.h"

using namespace std;
using i64 = long long;

const int B[] = {114514, 223333};
const int P = 2147483629;

i64 *p[2];

void init(int N) {
    p[0] = new i64 [N];
    p[1] = new i64 [N];
    p[0][0] = p[1][0] = 1;
    for (int i = 1; i <= N; i++) {
        p[0][i] = p[0][i - 1] * B[0] % P;
        p[1][i] = p[1][i - 1] * B[1] % P;
    }
}

struct StringHash2D {
    int n, m;
    vector<vector<i64>> h;
    StringHash2D(const vector<string> &a) {
        n = a.size();
        m = (n == 0 ? 0 : a[0].size());
        h.assign(n + 1, {});
        for (int i = 0; i <= n; i++) {
            h[i].assign(m + 1, 0);
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                h[i + 1][j + 1] = (h[i][j + 1] * B[0] % P + h[i + 1][j] * B[1] % P + 
                    (P - h[i][j]) * B[0] % P * B[1] % P + a[i][j]) % P; 
            }
        }
    }

    i64 get(int x1, int y1, int x2, int y2) { // p1 = (x1, y1) p2 = (x2, y2) [p1, p2)
        return (h[x2][y2] + h[x1][y1] * p[0][x2 - x1] % P * p[1][y2 - y1] % P + 
            (P - h[x1][y2]) * p[0][x2 - x1] % P + (P - h[x2][y1]) * p[1][y2 - y1] % P) % P;
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    init(2E3);

    int n, m;
    cin >> n >> m;

    vector<string> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    
    auto b = a;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            b[i][j] = a[n - 1 - i][m - 1 - j];
        }
    } 

    StringHash2D hs1(a), hs2(b);

    auto same = [&](int x1, int y1, int x2, int y2) {
        return hs1.get(x1, y1, x2, y2) == hs2.get(n - x2, m - y2, n - x1, m - y1);
    };
    
    i64 ans = 0;
    
    // odd 
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            int l = 1, r = min(min(i + 1, n - i), min(j + 1, m - j));
            while (l <= r) {
                int x = (l + r) >> 1;
                if (same(i - x + 1, j - x + 1, i + x, j + x)) {
                    l = x + 1;
                } else {
                    r = x - 1;
                }
            }
            ans += l - 1;
        }
    }

    // even
    for (int i = 1; i < n; i++) {
        for (int j = 1; j < m; j++) {
            int l = 1, r = min(min(i, n - i), min(j, m - j));
            while (l <= r) {
                int x = (l + r) >> 1;
                if (same(i - x, j - x, i + x, j + x)) {
                    l = x + 1;
                } else {
                    r = x - 1;
                }
            }
            ans += l - 1;
        }
    }
    cout << ans << '\n';

    return 0;
}

H

哥德巴赫猜想在题目范围内正确。

C++ Code
#include "bits/stdc++.h"

using namespace std;
using i64 = long long;

bool isprime(int x) {
    if (x < 2) {
        return false;
    }    
    for (int i = 2; i64(i) * i <= x; i++) {
        if (x % i == 0) {
            return false;
        }
    }
    return true;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin >> n;
    vector<int> a(n);
    i64 sum = 0;
    for (int i = 0; i < n;i++) {
        cin >> a[i];
        sum += a[i];
    }
    
    if (n == 1) {
        cout << (isprime(a[0]) ? "Yes" : "No") << '\n';
    } else if (n == 2) {
        if (sum % 2) {
            cout << (isprime(sum - 2) ? "Yes" : "No") << '\n';
        } else {
            cout << (sum > 2 ? "Yes" : "No") << '\n';
        }
    } else {
        cout << (sum >= 2 * n ? "Yes" : "No") << '\n';
    }

    return 0;
}

I

答案为 的距离加转换颜色次数。

看成

C++ Code
#include "bits/stdc++.h"

using namespace std;
using i64 = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n, q;
    cin >> n >> q;

    vector<i64> c(n);
    for (int i = 0; i < n; i++) {
        cin >> c[i];
    }
  
    vector<vector<int>> g(n);
    for (int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;

        u--, v--;
        g[u].push_back(v);
        g[v].push_back(u);
    }

    int lg = __lg(n);
    vector<int> dep(n);
    vector<vector<int>> p(lg + 1, vector<int>(n, -1));
    vector<vector<i64>> sum(lg + 1, vector<i64>(n));
    auto f = p;
  
    function<void(int, int)> dfs = [&](int cur, int pre) {
        for (int i = 0; (2 << i) <= dep[cur]; i++) {
            p[i + 1][cur] = p[i][p[i][cur]];
            sum[i + 1][cur] = sum[i][p[i][cur]] & sum[i][cur];
        }

        int u = cur;
        i64 col = c[u];
        for (int i = lg; i >= 0; i--) {
            if (col & sum[i][u]) {
                col &= sum[i][u];
                u = p[i][u];
            }
        }
  
        f[0][cur] = u;
        for (int i = 0; (2 << i) <= dep[cur]; i++) {
            f[i + 1][cur] = f[i][f[i][cur]];
        }       

        for (auto &nex : g[cur]) {
            if (nex != pre) {
                p[0][nex] = cur;
                dep[nex] = dep[cur] + 1;
                sum[0][nex] = c[cur] & c[nex];
                dfs(nex, cur);
            }
        }
    };

    auto lca = [&](int x, int y) {
        if (dep[x] < dep[y]) {
            swap(x, y);
        }
        for (int i = lg; i >= 0; i--) {
            if (dep[x] - dep[y] >= (1 << i)) {
                x = p[i][x];
            }
        }
        if (x == y) {
            return x;
        }
        for (int i = lg; i >= 0; i--) {
            if(p[i][x] != p[i][y]) {
                x = p[i][x];
                y = p[i][y];
            }
        }        
        return p[0][x];
    };
  
    dfs(0, -1);

    auto getCol = [&](int u, int v) {
        i64 res = c[u];
        for (int i = lg; i >= 0; i--) {
            if (dep[u] - dep[v] >= (1 << i)) {
                res &= sum[i][u];
                u = p[i][u];
            }
        }
        return res;
    };
  
    for (int i = 0; i < q; i++) {
        int u, v;
        cin >> u >> v;

        u--, v--;
        int m = lca(u, v);

        int ans = dep[u] + dep[v] - 2 * dep[m];
        for (int i = lg; i >= 0; i--) {
            if (dep[f[i][u]] > dep[m]) {
                ans += 1 << i;
                u = f[i][u];
            } 
            if (dep[f[i][v]] > dep[m]) {
                ans += 1 << i;
                v = f[i][v];
            }
        }     
  
        i64 x = getCol(u, m);
        i64 y = getCol(v, m);
        if (!x || !y) {
            cout << "-1\n";
        } else {
            if (!(x & y)) {
                ans++;
            }
            cout << ans << '\n';
        }
    }
  
    return 0;
}

J

跑个拓扑序。

C++ Code
#include "bits/stdc++.h"

using namespace std;
using i64 = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n, m;
    cin >> n >> m;
    vector<vector<int>> g(n);
    vector<int> deg(n);
    for (int i = 0; i < m; i++) {
        int u, v;
        cin >> u >> v;

        u--, v--;
        g[u].push_back(v);
        deg[v]++;
    }

    vector<int> ans;
    for (int i = 0; i < n; i++) {
        if (!deg[i]) {
            ans.push_back(i);
        }
    }
    for (int i = 0; i < (int) ans.size(); i++) {
        int cur = ans[i];
        for (auto &nex : g[cur]) {
            if (!--deg[nex]) {
                ans.push_back(nex);
            }
        } 
    }

    if (ans.size() == n) {
        cout << "1\n";
        for (int i = 0; i < n; i++) {
            cout << ans[i] + 1 << " \n"[i == n - 1];
        }
    } else {
        cout << "2\n";
        for (int i = 1; i <= n; i++) {
            cout << i << " \n"[i == n];
        }
        for (int i = n; i >= 1; i--) {
            cout << i << " \n"[i == n];
        }
    }

    return 0;
}
全部评论
求求E的代码qwq, 一直想不明白那个f[i]该怎么求
点赞 回复 分享
发布于 2023-07-26 11:31 福建

相关推荐

不愿透露姓名的神秘牛友
07-11 11:24
大家还是用ai改吧,我心疼得要死,就当花钱买教训吧,人家直接拿完钱就跑路了
程序员小白条:简历修改700....神奇,又不是帮你面试,咋的,简历修改从双非变92了还是没实习变成有大厂实习了
点赞 评论 收藏
分享
MinJerous:虽然我一直说 计算机不怎么卡学历 但是至少得一本
点赞 评论 收藏
分享
谈到工资分配问题,我首先想到的就是这句话。当我第一次出门实习又离开后,失去了一个月的押金,妈妈和我吵了一架,妈妈没有出过门,不知道一线城市生活有多么不容易,我的花费其实并不算高,大学里我的每月生活费也只有800块,但是对于我的家庭来说,觉得那1550的押金,还有1次出去音乐节玩(当然这个我没有敢告诉,我只向妈妈要了每周200的生活费和押一付一的租房钱),是我没有为家庭考虑。我第一次认真算了我的开销,似乎对我的家庭来说,这样的花费是有点高,我已经出去实习了,靠花呗,这每周200的生活费其实是可以省下不管妈妈要的。我的老师认真听了我的经历,讲了她的故事,又讲了她对我的印象,“走马观花去复旦校园逛一...
电牛小子_:老哥真不容易,想起我三个月的实习了,直到实习结束才告诉家里,老师同学家人谁都不知道我在外面实习,花的是自己攒的钱,租金被中介黑,每个月飞两次回学校考试,每次都买红眼航班比较便宜 ,常常两点钟还在回学校回出租屋的路上,第二天就要上班或者考试,这学期还把大一大二的挂科重修过了,我觉得我还是很厉害的,经历这些后,我多了一份从容,感觉什么困难都能克服了
每个月的工资都是怎么分配...
点赞 评论 收藏
分享
评论
8
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务