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

CF1523D Love-Hate 题解

时间:2023-10-24 15:24:56浏览次数:38  
标签:le int 题解 pos CF1523D limit 集合 Hate dp

抽象化题意:

一共有 \(m\) 个元素,给定 \(n\) 个集合,每个集合的元素不超过 \(15\) 个,求出一个元素个数最多的集合 \(S\) 是至少 \(\lceil \dfrac{n}{2} \rceil\) 个集合的子集。

其中$ p $ $ (1 \le n \le 2 \cdot 10^5, 1 \le p \le m \le 60) $

我们先假设 \(limit= \lceil \dfrac{n}{2} \rceil\)

先考虑最基础的暴力,如果我们每次枚举答案集合 \(S\) ,然后再计算出是否有大于等于 \(limit\) 个集合是 \(S\) 的超集,更新答案

计算超集可以通过 \(SOSDP\) ,仍然TLE,先从题目本质入手,它是让我们求一个集合使得是至少 \(\lceil \dfrac{n}{2} \rceil\) 个集合的子集,那么这个答案显然是某 \(\lceil \dfrac{n}{2} \rceil\) 个集合的子集,那如果我们随机任取一个集合,正确答案是它子集的概率就是50%,那我们直接随 \(num\) 次,可以直接让答案错误的概率降到极低,错误的概率就是 \(\dfrac{1}{2^{num}}\) 。

也就是说随机50次的样子,每次对于随机到的集合,通过 \(O(p\times2^p)\) 来计算超集,具体细节就是需要搞个vector来存某位是1的位置就行了。

代码:

#include<bits/stdc++.h>

#define int long long 
 
using namespace std;
 
template<class T>
 
inline T read(){
	T r=0,f=0;
	char c;
	while(!isdigit(c=getchar()))f|=(c=='-');
	while(isdigit(c))r=(r*10)+(c^48),c=getchar();
	return f?-r:r;
}

int n,m,p,limit;
 
int a[200005];
 
bool flag[200005];
 
vector<int>g;
 
inline int idx(char c){
	return c-'0';
}
 
int dp[1000005];

int ans;

mt19937 rd(time(0));
 
inline void work(){
	int pos;
	while(1){
		pos=rd()%n+1;
		if(!flag[pos]){flag[pos]=true;break;}
	}
	g.clear();
	int num=a[pos];
	for(int i=0;i<m;i++){
		if((num>>i)&1)g.emplace_back(i);
	}
	memset(dp,0,sizeof(dp));
	int S=g.size();
	for(int i=1;i<=n;i++){
		int tmp=0;
		for(int j=0;j<S;j++){
			if((a[i]>>g[j])&1)tmp|=(1<<j);
		}
		++dp[tmp];
	}
	for(int i=0;i<S;i++){
		for(int j=0;j<(1ll<<S);j++){
			if(!((j>>i)&1))dp[j]+=dp[j^(1<<i)];
		}
	}
	int res=0;
	for(int i=1;i<(1ll<<S);i++){
		if(dp[i]>=limit){
			if(__builtin_popcountll(res)<__builtin_popcountll(i))res=i;
		}
	}
	int res2=0;
	for(int i=0;i<S;i++){
		if((res>>i)&1)res2|=(1ll<<g[i]);
	}
	if(__builtin_popcountll(res)>__builtin_popcountll(ans))ans=res2;
}
 
signed main(){
	n=read<int>(),m=read<int>(),p=read<int>();
	limit=(n+1)>>1;
	for(int i=1;i<=n;i++){
		char c;
		for(int j=0;j<m;j++){
			cin>>c;
			if(idx(c))a[i]|=(1ll<<j);
		}
	}
	for(int t=1;t<=min(n,50ll);t++)work();
	for(int i=0;i<m;i++)
		((ans>>i)&1)?putchar('1'):putchar('0');
	puts("");
	return 0;
}

标签:le,int,题解,pos,CF1523D,limit,集合,Hate,dp
From: https://www.cnblogs.com/blueparrot/p/17784872.html

相关文章

  • 2023级HAUT新生周赛题解汇总
    2023级HAUT新生周赛(零)熟悉周赛规则专场:2023级HAUT新生周赛(一)@21级学长专场(张子豪,张鑫,李昊阳):2023级HAUT新生周赛(二)@曹瑞峰专场:2023级HAUT新生周赛(三)@22级学姐专场(杨焱,刘振歌,周欣滢):2023级HAUT新生周赛(四)@牛浩然专场:2023级HAUT新生周赛(五)@陈兰锴专场:......
  • JWT Tool:针对 JSON Web Tokens 的测试工具题解JWT cracking
    什么是JWT?JWT是JSONWebToken的缩写,它是一串带有声明信息的字符串,由服务端使用加密算法对信息签名,以保证其完整性和不可伪造性。Token里可以包含所有必要的信息,这样服务端就无需保存任何关于用户或会话的信息了。JWT可用于身份认证,会话状态维持以及信息交换等任务。JWT由三部分......
  • CSP20230917-3 梯度求解 题解
    〇、题目太长了懒得写。简单来说就是求对于一个后缀表达式,每个询问给出一个下标和一些值,求以该下标变量为自变量其它变量为常数时的偏导数。一、思路考虑直接对于表达式建出表达式树。建树的过程比较直接:每次栈里面放节点编号,遇到符号就取出当前栈顶两个节点作为子节点。每......
  • Codeforces Round 886 (Div. 4) 题解
    link我为什么还要vpdiv4场。。。A直接找最大的两个判断一下。voidsolve(){ inta[3]; cin>>a[0]>>a[1]>>a[2]; sort(a,a+3); if(a[2]+a[1]>=10)cout<<"YES\n"; elsecout<<"NO\n";}B按照题目意思模拟。voidsolv......
  • P3657 题解
    是不是有点恶意评分了题目链接Sol看完题目就想到了这个题。这道题同样是求线段,不过这个加了点限制,发现一个点最多连4条边出去,暴力连边的复杂度是正确的,于是就把这题变成黄了。利用刚刚那道题的trick,把边按左端点排序后右端点的LIS就是答案。这里给一个更方便的做法,不用......
  • P2679 [NOIP2015 提高组] 子串 题解
    #include<bits/stdc++.h>usingnamespacestd;#defineintlonglongconstintMOD=1000000007;intn,m,k,dp[205][205][2];charA[1005],B[205];signedmain(){cin.tie(0)->sync_with_stdio(0);cin>>n>>m>>k;cin......
  • P9754 [CSP-S 2023] 结构体 题解
    考前内心OS:“CCF不会出大模拟吧(((”。前置声明辅助函数:偏移量考虑一个结构体的偏移量。已知首个空地址\(\mathrm{address}\)和该结构体的对齐要求\(\mathrm{align}\),则该结构体正确的起始地址为\(\mathrm{\lceiladdress/align\rceil\timesalign}\)。i64shiftToAl......
  • CF1710 题解
    CF1710题解A看图写话。想象一个格子以及周围同色格的颜色必须呈一个三叉的形状:################这些三叉拼起来最小的形状,就是两个以上的整行,或整列。所以遍历每一种颜色,通过整......
  • CSP-S 2023 游记 & 总结 & 题解
    游记到了机房发现是Windows10,感觉不错。比赛开始果断启动虚拟机,怎么今年PDF密码这么复杂啊,我记得去年挺简单的来着,好像是believe2022?看了一遍题,有理由怀疑T1是J的题,但是一开始读错了,以为只能转一下,后来计算转动幅度的时候忘记对\(10\)取模,怒调1h。T2一开始以为是容......
  • 【题解】CF1710 合集
    CF1710AColorthePicture标签:思维题\(C^-\)典型的有图有真相,嘻嘻(抽风了?显然有一个结论,我们颜色要么一行一行天,要么一列一列填。并且填进去的颜色必须不少于两行/列然后就是记一个ans和一个over表示如果每个颜色都两行/列填进去能填的最多列数,以及两行/列填进去后还能......