牛客挑战赛47

牛客挑战赛47

A 一道GCD问题

加个相同的数, gcd最大, 相当于所有数 % maxgcd 的余数相同

每个数相互减一下, 余数就被减没了

int main() {
    IOS; cin >> n;
    rep (i, 1, n) cin >> a[i]; sort(a + 1, a + 1 + n);
    a[n] -= a[n - 1];
    per (i, n - 1, 2) a[i] -= a[i - 1], a[n] = __gcd(a[n], a[i]);
    cout << a[n] << ' ' << (a[n] - a[1] % a[n]) % a[n];
    return 0;
}

B 又一道 GCD 问题

记录每个因子出现的次数就好了

int c[N], b[N], ans[N];

int main() {
    IOS; cin >> n;
    rep (i, 1, n) {
        cin >> m;
        rep (j, 1, m / j) if (m % j == 0)
            if (j == m / j) ++c[j];
            else ++c[j], ++c[m / j];
    }
    rep (i, 1, 1e5) b[c[i]] = i;
    per (i, n, 2) ans[i] = max(ans[i + 1], b[i]);
    rep (i, 2, n) cout << ans[i] << ' ';
    return 0;
}

C 条件

本来想用弗洛伊德做的结果 \(O(n^3)\) 妥妥超时

那就改成每个点跑一边迪杰斯特拉 \(O(n^2logn)\) 复杂度还行

VI e[2][N];
int d[2][N][N], g[N][N];
bool v[2][N][N];

void dij(int s, int* d, bool* v, VI* e) {
    rep(i, 1, n) d[i] = 1e9; d[s] = 0;
    priority_queue<PII> q; q.push({ 0, s });
    while (!q.empty()) {
        int x = q.top().se; q.pop();
        if (v[x]) continue; v[x] = 1;
        for (auto& y : e[x]) 
            if (d[y] > d[x] + 1) 
                q.push({ -(d[y] = d[x] + 1), y });
    }
}

int main() {
    IOS; cin >> n >> m1 >> m2 >> k;
    rep(i, 1, m1) {
        int x, y; cin >> x >> y;
        e[0][x].pb(y);
    }
    rep(i, 1, n) dij(i, d[0][i], v[0][i], e[0]), g[i][i] = 1;
    rep(i, 1, m2) {
        int x, y; cin >> x >> y;
        g[x][y] = 1;
    }
    rep(i, 1, n) rep(j, 1, n) if (!g[i][j]) e[1][i].pb(j);
    rep(i, 1, n) dij(i, d[1][i], v[1][i], e[1]);
    rep(i, 1, k) {
        int x, y; cin >> x >> y;
        cout << (d[0][x][y] < 1e9 ? "Yes " : "No ") << (d[1][x][y] < 1e9 ? "Yes\n" : "No\n");
    }
    return 0;
}

我的天, 评测姬nb, 弗洛伊德过了, 数据估计是随机的, 快了700ms+, 慢了t了

int main() {
    read(n, m1, m2, k);
    rep (i, 1, n) d[i][i] = 1;
    rep (i, 1, m1) { read(x, y); d[x][y] = 1; }
    rep (i, 1, m2) { read(x, y); d[x][y] = -1; }
    rep (k, 1, n) rep (i, 1, n) rep (j, 1, n) umax(d[i][j], min(d[i][k], d[k][j]));
    rep (i, 1, k) {
        read(x, y);
        switch (read(x, y), d[x][y]) {
            case 1 : puts("Yes Yes"); break;
            case 0 : puts("No Yes"); break;
            case -1 : puts("No No");
        }
    }
    return 0;
}

⭐D Lots of Edges

把点变成权值, 跑迪杰斯特拉就行, 边权都是 0, 1, 直接双端队列就行, 挺好的一道题

int d[N], a[N], c = (1 << 17) - 1;
bool v[N], b[N];

void dij(int s) {
    memset(d, 0x3f, sizeof d); d[c ^ s] = v[s] = 1;
    deque<int> q; q.push_back(c ^ s);
    while (!q.empty()) {
        int x = q.front(); q.pop_front();
        if (v[x]) continue; v[x] = 1;
        rep (i, 0, 16) if (x >> i & 1) if (d[x ^ (1 << i)] > d[x])
            d[x ^ (1 << i)] = d[x], q.push_front(x ^ (1 << i));
        if (b[x] && d[c ^ x] > d[x] + 1) d[c ^ x] = d[x] + 1, q.push_back(c ^ x);
    }
}

int main() {
    IOS; cin >> n >> m;
    rep (i, 1, n) cin >> a[i], b[a[i]] = 1; dij(a[m]);
    rep (i, 1, n) cout << (i == m ? 0 : d[a[i]] == d[N - 1] ? -1 : d[a[i]]) << ' ';
    return 0;
}
posted @ 2021-01-10 11:08  洛绫璃  阅读(113)  评论(0编辑  收藏  举报