Codeforces Global Round 14

Codeforces Global Round 14

A - Phoenix and Gold

int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n >> m;
        rep (i, 1, n) cin >> a[i];
        sort(a + 1, a + 1 + n);
        int x = 1, s = 0; queue<int> q;
        for (; x <= n; ++x) {
            s += a[x];
            if (s == m && q.empty() && x == n) break;
            else if (s == m && (q.empty() || q.front() == a[x])) {
                int y = x + 1;
                while (y <= n && a[y] == a[x]) ++y;
                if (y > n) break;
                q.push(a[y]);
                while (x < y) q.push(a[x++]), s += a[x];
            }
            else if (s == m && x == n) break;
            else if (s == m) {
                q.push(a[x]); q.push(a[++x]); q.push(q.front());
                q.pop(); s += a[x];
            }
            else q.push(a[x]);
        }
        if (s == m) cout << "NO
";
        else {
            cout << "YES
";
            while (!q.empty()) cout << q.front() << ' ', q.pop();
            cout << '
';
        }
    }
    return 0;
}

B - Phoenix and Puzzle

int main() {
    IOS; set<int> st; n = 1;
    while (1) {
        st.insert(n * n); ++n;
        if (n >= 1e9 / n) break;
    }
    for (cin >> _; _; --_) {
        cin >> n;
        if (n & 1) cout << "NO
";
        else if (st.count(n >> 1)) cout << "YES
";
        else if (n >> 1 & 1) cout << "NO
";
        else if (st.count(n >> 2)) cout << "YES
";
        else cout << "NO
";
    }
    return 0;
}

C - Phoenix and Towers

贪心

int main() {
    IOS;
    for (cin >> _; _; --_) {
        priority_queue<PII> q;
        cin >> n >> m >> k; cout << "YES
";
        rep (i, 1, m) q.push({ 0, i });
        rep (i, 1, n) {
            cin >> cas;
            auto x = q.top(); q.pop();
            cout << x.se << ' ';
            x.fi -= cas; q.push(x);
        }
        cout << '
';
    }
    return 0;
}

D - Phoenix and Socks

int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> k >> n >> m; map<int, int> a, b;
        int x = n, y = m, d = 0;
        rep (i, 1, n) cin >> cas, ++a[cas];
        rep (i, 1, m) {
            cin >> cas;
            if (a[cas]) --a[cas], --x, --y;
            else ++b[cas];
        }
        if (x == y) { cout << x << '
'; continue; }
        if (x < y) swap(a, b), swap(x, y);
        for (auto &i : a) d += i.se >> 1;
        if (d >= x - y >> 1) cout <<  y + (x - y >> 1) << '
';
        else cout << y + (x - y - d * 2) + d << '
';
    }
    return 0;
}

E - Phoenix and Computers

线性dp

首先, 假设开([l, r]) 开了 (r-l+1) 台电脑, 则必定是从一台电脑, 不断左右边界反复横跳开电脑

即方案数为(2^{r-l+1})

当使用题目给的自动开启方案时, 注意到按区间dp的话

([l, k], [k + 2, g], [g + 2, r])([k + 2, g]) 归于左边(([l, k], [k + 2, r]))或右边(([l, g], [g + 2, r])) 都是可行的

但会多算

故我们在扩展范围的时候除了不使用自动开启方案, 则保证扩展的部分([k, r]) 没用使用自动开启

则每次扩展扩展使用一次自动开启([l, k], [k + 2, r]), 去重, 变成了线性dp

(f(i, j)) 表示前(i) 台电脑手动开了 (j) 次,

(f(i, i) = 2^{i - 1})

(f(i + 1 + k, j + k) += f(i, j) * 2^{k - 1} * C_{j + k}^{k})

int mod, f[N][N], qp[N];
int fac[N], facinv[N], inv[N];

int C(int n, int m) { return (ll)fac[n] * facinv[m] % mod * facinv[n - m] % mod; }

void init(int n) {
    fac[0] = fac[1] = facinv[0] = facinv[1] = inv[0] = inv[1] = qp[0] = 1; qp[1] = 2;
    rep (i, 2, n)
        qp[i] = (ll)(qp[i - 1] << 1) % mod,
        fac[i] = (ll)fac[i - 1] * i % mod,
        inv[i] = (ll)(mod - mod / i) * inv[mod % i] % mod,
        facinv[i] = (ll)facinv[i - 1] * inv[i] % mod;
}

int main() {
    IOS; cin >> n >> mod; init(n);
    rep (i, 1, n) f[i][i] = qp[i - 1];
    rep (i, 1, n) rep (j, 1, n) rep (k, 1, n - 1 - i)
        f[i + k + 1][j + k] = (f[i + k + 1][j + k] + (ll)f[i][j] * qp[k - 1] % mod * C(j + k, k) % mod) % mod;
    rep (i, 1, n) m = (m + f[n][i]) % mod; cout << m;
    return 0;
}

注意到当 (sum a_i geqslant x imes (n - 1)) 必定有解

可用归纳法和反证法

否则无解

就变成了选编的顺序

毕竟是颗树, 那就dfs完事

到达叶子节点

如果(a_i geqslant x) 则这条边肯定先选择, 并且把多余的 (a_i - x) 水泥贡献给父亲节点

否则 这条边最后选(最后的时候, 多余的水泥会从父亲节点传过来)

ll a[N], s;
int ans[N], l, r, g[N][2];
VI h[N];
bool v[N];

int get(int x, int e) { return g[e][0] ^ g[e][1] ^ x; }
 
void dfs(int x, int e) {
	v[x] = 1;
	for (auto &id : h[x]) if (!v[get(x, id)]) dfs(get(x, id), id);
	if (!e) return;
	if (a[x] >= k) ans[++l] = e, a[get(x, e)] += a[x] - k;
	else ans[--r] = e;
}

int main() {
    IOS; cin >> n >> m >> k; r = n;
    rep (i, 1, n) cin >> a[i], s += a[i];
    if (n - 1 > s / k) return cout << "NO
", 0;
    rep (i, 1, m) rep (j, 0, 1) cin >> g[i][j], h[g[i][j]].pb(i);
    dfs(1, 0); cout << "YES
";
    rep (i, 1, n - 1) cout << ans[i] << '
';
    return 0;
}
原文地址:https://www.cnblogs.com/2aptx4869/p/14727379.html