[Codeforces 1523D] Love-Hate

https://codeforces.ml/contest/1523/problem/D
题意:
现在有\(m\)种货币,每个人最多会喜欢\(p\)种货币。现在要选择最多的货币,使得不少于一半的人都喜欢这些货币,输出其中的一种方案。

思路:
要不少于一半,很容易想到我们随机去取一个人,就有\(\frac{1}{2}\)的概率能取到在最终集合中的人。\(m\)太大了,但是\(p \leq 15\),选取一个人的时候,把他喜欢的货币序号给取出来,就能用二进制来表示了。设我们选取的人为\(i\),我们枚举\(j\),假设j和i都属于最终的集合,把他们最大相同的货币情况取出来,转换为10进制,用数组存下来。然后,我们再考虑其中不选取某个货币的情况。注意枚举货币的状态要从小到大枚举,避免重复计数。这样子就得到了选取第\(i\)的人的情况下,所有货币选取情况的可参与人数了,维护答案的最大值就行了。

关于rng随机数,贴个链接mark一下。
https://codeforces.com/blog/entry/61587

#include <bits/stdc++.h>

using namespace std;

#define endl "\n"

typedef long long ll;

const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int N = 2e5 + 7;

int n, m, p;
ll a[N];

void solve() {
    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
    cin >> n >> m >> p;
    for (int i = 0; i < n; ++i) {
       string s;
       cin >> s;
        for (int j = 0; j < m; ++j) {
            if (s[j] == '1') a[i] |= 1ll << j;
        }
    }
    vector<int> G(n);
    iota(G.begin(), G.end(), 0);
    shuffle(G.begin(), G.end(), rng);
    string ans(m, '0');
    int res = 0;
    for (int i = 0; i < min(n, 100); ++i) {
        int v = G[i];
        vector<int> V;
        for (int j = 0; j < m; ++j) {
            if ((a[v] >> j) & 1) V.push_back(j);
        }
        int sz = V.size();
        vector<int> nums(1 << sz);
        for (int j = 0; j < n; ++j) {
            int u = 0;
            for (int k = 0; k < sz; ++k) {
                if ((1ll << V[k]) & a[j]) u |= 1 << k;
            }
            nums[u]++;
        }
        for (int j = 0; j < sz; ++j) {
            for (int k = 0; k < (1 << sz); ++k) {
                if (k & (1 << j)) {
                    nums[k ^ (1 << j)] += nums[k];
                }
            }
        }
        for (int j = 0; j < (1 << sz); ++j) {
            if (nums[j] * 2 >= n) {
                if (__builtin_popcount(j) > res) {
                    res = __builtin_popcount(j);
                    ans = string(m, '0');
                    for (int k = 0; k < sz; ++k) {
                        if (j & (1 << k)) ans[ V[k] ] = '1';
                    }
                }
            }
        }
    }
    cout << ans << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);cout.tie(nullptr);
    cout << fixed << setprecision(20);
    int t = 1;
    //cin >> t;
    // t = rd();
    while (t--) solve();
    return 0;
}
上一篇:I love Java(2)


下一篇:python数据结构-列表-1