ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[Codeforces 1523D] Love-Hate

2021-07-15 11:34:26  阅读:314  来源: 互联网

标签:Love int ll rng 选取 ++ 货币 1523D 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;
}

标签:Love,int,ll,rng,选取,++,货币,1523D,Hate
来源: https://www.cnblogs.com/Sstee1XD/p/15014676.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有