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\n";
        else {
            cout << "YES\n";
            while (!q.empty()) cout << q.front() << ' ', q.pop();
            cout << '\n';
        }
    }
    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\n";
        else if (st.count(n >> 1)) cout << "YES\n";
        else if (n >> 1 & 1) cout << "NO\n";
        else if (st.count(n >> 2)) cout << "YES\n";
        else cout << "NO\n";
    }
    return 0;
}
C - Phoenix and Towers
贪心
int main() {
    IOS;
    for (cin >> _; _; --_) {
        priority_queue<PII> q;
        cin >> n >> m >> k; cout << "YES\n";
        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 << '\n';
    }
    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 << '\n'; 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) << '\n';
        else cout << y + (x - y - d * 2) + d << '\n';
    }
    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 \times (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\n", 0;
    rep (i, 1, m) rep (j, 0, 1) cin >> g[i][j], h[g[i][j]].pb(i);
    dfs(1, 0); cout << "YES\n";
    rep (i, 1, n - 1) cout << ans[i] << '\n';
    return 0;
}
 
                    
                
 
     
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号