首页 > 其他分享 >CF1523D Love-Hate 题解

CF1523D Love-Hate 题解

时间:2024-07-29 19:30:50浏览次数:17  
标签:__ CF1523D int 题解 LL 子集 集合 now Hate

CF1523D Love-Hate 题解

传送门

题目大意:给定 \(m\) 和 \(n\) 个集合,而且这 \(n\) 个集合的元素都是 \(1\) ~ \(m\) 中的数且没有重复,而且大小都不超过 \(15\)。求一个最大的集合,使得这个集合是至少 \(\left\lceil\frac{n}{2}\right\rceil\) 个集合的子集。


先想一个问题:题目是让求集合是任意 \(\left\lceil\frac{n}{2}\right\rceil\) 个集合的子集,那如果我们已经知道它是其中一个给定集合的子集,该怎么求?

这个其实很好算,先让所有集合只保留这个集合有的元素,然后另 \(f_i\) 表示状态为 \(i\) 的这个集合是多少个集合的子集,然后就可以 \(\mathcal{O}(n+p\times 2^p)\) 来求了。

那么回到原题,我们怎么知道这个集合是哪个集合?

假设我们随机选一个,那么最终答案集合不是该子集的可能性仅为 \(\frac{1}{2}\)。

如果我们随机选 \(k\) 个,那么都不是答案的可能就是 \(\frac{1}{2^k}\)。

当 \(k=50\) 时,基本上已经完全不可能了,此时时间复杂度为 \(\mathcal{O}(k\times(n+p\times 2^p))\)。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const LL mod = 1e9 + 7;
const int N = 200005;

LL a[N];
char s[100];
int f[1 << 15];
int main() {
    int n, m;
    scanf("%d%d%*d", &n, &m);
    for (int i = 0; i < n; i++) {
        scanf("%s", s);
        for (int j = 0; j < m; j++) {
            if (s[j] == '1') a[i] ^= 1LL << j;
        }
    }
    mt19937 g(time(0));
    uniform_int_distribution<int> u1(0, n - 1);
    LL ans = 0;
    int T = 50;
    while (T--) {
        vector<int> b;
        LL ak = a[u1(g)];
        for (int i = 0; i < m; i++) {
            if (ak >> i & 1) b.push_back(i);
        }
        memset(f, 0, sizeof f);
        for (int i = 0; i < n; i++) {
            int t = 0;
            for (int j = 0; j < b.size(); j++) {
                if (a[i] >> b[j] & 1) {
                    t ^= 1 << j;
                }
            }
            f[t]++;
        }

        for (int i = 0; i < b.size(); i++) {
            for (int j = 0; j < 1 << b.size(); j++) {
                if ((j >> i & 1) == 0) f[j] += f[j ^ 1 << i];
            }
        }
        int now = 0;
        for (int i = 0; i < 1 << b.size(); i++) {
            if (f[i] * 2 >= n && __builtin_popcount(i) > __builtin_popcount(now)) now = i;
        }
        if (__builtin_popcount(now) > __builtin_popcountll(ans)) {
            ans = 0;
            for (int i = 0; i < b.size(); i++) {
                if (now >> i & 1) ans ^= 1LL << b[i];
            }
        }
    }
    for (int i = 0; i < m; i++) {
        printf("%d", ans >> i & 1);
    }
    putchar('\n');
    return 0;
}

标签:__,CF1523D,int,题解,LL,子集,集合,now,Hate
From: https://www.cnblogs.com/max0810/p/18330854

相关文章

  • CF1523E Crypto Lights 题解
    CF1523ECryptoLights题解传送门。题目大意:有\(n\)个台灯,初始时都是暗的,每次随机点亮一个暗台灯,若点亮后存在一个长度为\(k\)的连续段有大于一个台灯被点亮则立刻停止,求期望点亮多少台灯。(就是直接把原题翻译搬过来了)很明显的期望dp,状态定义也很明显,设\(f_i\)表示......
  • P8347 「Wdoi-6」另一侧的月 题解
    P8347「Wdoi-6」另一侧的月题解第一次自己思考出来紫题,题解纪念一下。下面为大家讲解如何一步步推到最终结论:首先,原树没有根,不妨设它的根为\(1\),将它转化成有根的,便于操作。为了方便描述,我们称将一个非根节点的点的父亲删去,保留含这个点的连通块这个操作为截取操作(就是......
  • CF538G Berserk Robot 题解
    Description有一个机器人,第\(0\)秒时在\((0,0)\)位置。机器人会循环执行一个长度为\(l\)的指令序列,每秒执行一个指令。指令有ULDR四种,分别代表向上/左/下/右移动一格。你不知道这个指令序列具体是什么,但是你知道\(n\)条信息,第\(i\)条信息为「第\(t_i\)秒时机器......
  • CF1634F Fibonacci Additions 题解
    CF1634FFibonacciAdditions题解传送门。题目大意:给定两个序列\(A\)和\(B\),每次一个可以选一个区间,并在区间的第\(i\)个数加上\(F_i\),其中\(F\)是斐波那契数列,你需要在每次询问结束时输出两个序列是否相等。可以先求一个序列\(C\)表示\(A\)和\(B\)每个位置的......
  • 剑指Offer题解合集
    剑指Offer题单及题解题目顺序为牛客上剑指Offer专题JZ3、数组中重复的数字分析可以直接对数组进行排序,通过判断首末数字大小来判断数字越界情况,注意数组为空的情况。发现\(0\leqnums[i]\leqn-1\),因此直接开一个数组判断是否有重复数字即可,返回第一个重复数字。代码......
  • 力扣题解2-两数相加
    问题的描述如下:分析过程:为了解决这个问题,我们需要逐位相加两个链表对应位置的值,并处理进位问题。具体步骤如下:初始化一个新的链表,用于存储结果。使用两个指针遍历两个输入链表,逐位相加,同时考虑进位。如果一个链表比另一个短,则将其视为0进行计算。处理最后可能存在的进位......
  • curl发送get和post请求时遇到&截断的问题解决
    get的parameter里带&被截断处理第一种是双引号括住 第二种是加反斜杠转义 post请求的body里有参数的value带了&curl-XPOSThttp://qa-ci.fuxi.netease.com:36800/job/xxxxx/xxxx--userxxxx:xxxxx-d token=popo -d"msg=cd/ssd/deployment_bash&&bashkill.b......
  • P10812 【MX-S2-T3】跳 题解
    题目分析考虑DP。显然当没有\(i\)连向\(i+1\)的边时,整个图是一个DAG,可以直接DP。所以我们DP要解决的唯一问题,就是考虑上\(i\)到\(i+1\)的边。考虑从\(n\)走到\(1\)的过程。当我们从\(i\)向前跳到\(j\)后,此时我们要么向前跳,要么往回走。又因为不能经过重复......
  • CF30E Tricky and Clever Password 题解
    考虑先贪心中间的回文串\(b\),因为这即使影响了两边的字符串,也不会改变最终的总串长。所以先使用manacher跑出来每个位置的最长回文半径。在考虑怎样找出最长的\(a\)和\(a'\)。可以二分答案,设此时答案为\(k\),找出的\(b\)串为\(s[l\dotsr]\),那么其合法的条件就是存在\(......
  • 关于网站安全狗卸载了仍然能拦截的问题解决
    关于网站安全狗卸载了仍然能拦截的问题解决如果你将所有safedog的文件删除的话,可能会导致Apache服务启动不了例如:这里没有提示相关安全狗的信息是因为我已经删除了Apache访问safedog的配置代码,只是提醒错误信息会如上图所示。导致这种原因的结果大概率是因为Apache的conf文件......