牛客挑战赛63

圣遗物

分析:

发现除了第一个位置以外 每个位置都有两种选择

#include <bits/stdc++.h>
using namespace std;

const int mod = 998244353;

int n, fac = 1;

int Pow (int a, int k) {
    int res = 1;
    for (; k; a = 1ll * a * a % mod, k >>= 1)
        if (k & 1) res = 1ll * res * a % mod;
    return res;
}

int main () {

    cin >> n;
    for (int i = 1; i <= n; i++) fac = 1ll * fac * i % mod;

    cout << 1ll * Pow(2, n - 1) * Pow(fac, mod - 2) % mod << endl;

    return 0;
}

#include <bits/stdc++.h>
using namespace std;

const int N = 1e3 + 10, M = 13;

int n, k, m, f[N][M + 1][1 << M];
pair <int, int> a[N];

int main () {

    scanf("%d%d%d", &n, &k, &m);
    for (int num, idx, i = 1; i <= n; i++) {
        scanf("%d%d", &a[i].first, &num);
        while (num--) scanf("%d", &idx), a[i].second |= (1 << idx - 1);
    }

    sort(a + 1, a + n + 1);
    int lim = (1 << m) - 1;
    memset(f, 128, sizeof f), f[0][0][0] = 0;
    for (int i = 0; i < n; i++)
        for (int j = 0; j <= m; j++)
            for (int S = 0; S <= lim; S++) {
                if (j < m) f[i + 1][j + 1][S | a[i + 1].second] = max(f[i + 1][j + 1][S | a[i + 1].second], f[i][j][S]);
                if (n - i <= k - j) f[i + 1][j][S] = max(f[i + 1][j][S], f[i][j][S] + a[i + 1].first);
                f[i + 1][j][S] = max(f[i + 1][j][S], f[i][j][S]);
            }

    long long ans = 0;
    for (int j = 0; j <= m; j++)
        for (int S = 0; S <= lim; S++)
            ans = max(ans, 1ll * __builtin_popcount(S) * f[n][j][S]);
    printf("%lld\n", ans);

    return 0;
}
posted @ 2022-09-24 09:47  wzx_believer  阅读(17)  评论(0编辑  收藏  举报