牛客练习赛74

牛客练习赛74

这次我是真的nt, 1h前四题, 之后一直发呆

看出来了E是弗洛伊德, 怎么也调不出来, 比赛结束一看

我的三重循环的第三重是错的, 还是理解不够, 对这些小算法还是理解有点偏差,

明明应该是 rep(j, 1, n) 被我硬是写成了 rep(j, i + 1, n) 这怎么可能跑出多源最短路呢?

我是sb, 不然能进前十的, 艹

A CCA的数列

签到没啥好说的

int main() {
    IOS; cin >> n;
    rep (i, 1, n) cin >> a[i];
    bool f = 1, g = 1, h = 1;
    rep (i, 3, n) {
        if (a[i] - a[i - 1] != a[2] - a[1]) f = 0;
        if (a[i] * 1.0 / a[i - 1] != a[2] * 1.0 / a[1]) g = 0;
        if (a[i] % a[i - 1] != a[2] % a[1]) h = 0;
    }
    if (f || g || h) cout << "YES\n";
    else cout << "NO\n";
    return 0;
}

B CCA的字符串

也是签到, 没啥好说的, 每次找到一个NowCoder, 就算一下贡献就好

char s[N], t[N] = "NowCoder";

bool check(char *s) {
    rep (i, 0, 7) if (s[i] != t[i]) return 0;
    return 1;
}

int main() {
    IOS; cin >> s;
    ll ans = 0, ls = 0, len = strlen(s);
    for (int i = 0; s[i]; ++i) {
        if (!check(s + i)) continue;
        ans += (i - ls + 1ll) * (len - i - 7); ls = i + 1;
    }
    cout << ans;
    return 0;
}

C CCA的矩阵

把矩阵转换一下, 变成他题目给定的矩阵即可, 给出转移方程

在原矩阵(a, b) 对应转换的矩阵 (a - b + n, a + b - 1)

剩下的就是跑个二位前缀和, 在特判在原矩阵上会不会锤子敲出界就好了

ll a[N][N];

int main() {
    IOS; cin >> n >> k; m = k; k = (k << 1) - 1; int nn = (n << 1) - 1;
    rep(i, 1, n) rep(j, 1, n) cin >> a[i - j + n][i + j - 1];
    per(i, nn, 1) per(j, nn, 1) a[i][j] += a[i + 1][j] + a[i][j + 1] - a[i + 1][j + 1];
    ll ans = 0;
    rep(i, 1, nn) rep(j, 1, nn) {
        if (i + j + 1 - n & 1) continue;
        int x = i + j + 1 - n >> 1, y = j + 1 - x;
        if (x > n - k + 1 || y < m || y > n - m + 1 || x < 1) continue;
        umax(ans, a[i][j] - a[i + k][j] - a[i][j + k] + a[i + k][j + k]);
    }
    cout << ans;
    return 0;
}

D CCA的图

先跑一次最大生成树, 记录第一次让 s, t合并的边的权值L,

再跑一遍最小生成树(生成边必须 >= L), 记录第一次让s, t合并的边的权值R

int s, t, f[N];
vector<pair<int, PII>> e;

int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); }

int kruskal(int k) {
    rep (i, 1, n) f[i] = i;
    for (auto &i : e) {
        if (i.fi < k) continue;
        int x = find(i.se.fi), y = find(i.se.se);
        if (x == y) continue;
        f[y] = x; x = find(s), y = find(t);
        if (x == y) return i.fi;
    }
    return -1;
}

int main() {
    IOS; cin >> n >> m >> s >> t;
    rep (i, 1, m) {
        int u, v, w; cin >> u >> v >> w;
        e.pb({ w, { u, v }});
    }
    sort(all(e), [&](pair<int, PII>& a, pair<int, PII>& b) {
        return a.fi > b.fi;
    });
    int L = kruskal(-2e9);
    sort(all(e), [&](pair<int, PII>& a, pair<int, PII>& b) {
        return a.fi < b.fi;
    });
    int R = kruskal(L);
    cout << L << ' ' << R;
    return 0;
}

E CCA的期望

统计一下每个点作为点对最短路上的节点的次数即可, md, 对弗洛伊德的理解还是不够

int b[N];
ll d[N][N], cnt[N];

ll qpow(ll a, ll b) {
    ll ans = 1;
    for (; b; b >>= 1, a = a * a % mod)
        if (b & 1) ans = ans * a % mod;
    return ans;
}

int main() {
    IOS; cin >> n >> m >> k;
    rep(i, 1, n) cin >> b[i];
    memset(d, 0x3f, sizeof d);
    rep(i, 1, m) {
        int u, v, c; cin >> u >> v >> c;
        d[u][v] = d[v][u] = min(d[v][u], (ll)c);
    }
    rep(i, 1, n) d[i][i] = 0;
    rep(o, 1, n) rep(i, 1, n) rep(j, 1, n) umin(d[i][j], d[i][o] + d[o][j]);
    rep(o, 1, n) rep(i, 1, n) rep(j, i + 1, n)
        if (d[i][o] + d[o][j] == d[i][j]) ++cnt[o];
    ll ans = 0, r = n * (n - 1) >> 1, p = qpow(r, mod - 2);
    rep(i, 1, n) 
        if (b[i] || cnt[i] == r) ans = (ans + 1) % mod;
        else {
            ll q = (r - cnt[i]) * p % mod;
            ans = (ans + 1 - qpow(q, k) + mod) % mod;
        }
    cout << ans;
    return 0;
}
posted @ 2020-12-21 10:43  洛绫璃  阅读(72)  评论(0编辑  收藏  举报