zoukankan      html  css  js  c++  java
  • 【题解】Codeforces1523D Love-Hate

    Codeforces1523D Love-Hate

    题意

    (n)个集合与和一个有(m)个元素的全集(U),每个集合都是(U)的子集,且每个集合大小不超过(p),求一个最大的(U)的子集(A),使得(A)至少是(n)个集合中(lceil frac{n}{2} ceil)个集合的子集。

    (1le nle 2 imes10^5,1le ple mle 60,1le ple 15)

    题解

    如果我么随机从(n)个和中随机选(k)个集合,再枚举它的子集作为答案。由于(A)至少是(n)个集合中(lceil frac{n}{2} ceil)个集合的子集,这样错误的概率为(frac{1}{2^k}),错误的概率很小,所以我们随机一定次数从(n)个集合中选集合然后验证。下面考虑如何快速验证一个集合是否满足条件。

    由于每个集合最多只有(p)个元素,我们只需考虑其他集合中这(p)个元素的存在情况。于是可以根据当前待验证的集合将其他集合表示为长度不超过(p)的位图,设他们分别为(a_i),不妨设当前集合为(a_1),则其一个子集(b(b&a_1=b,b|a_1=a_1))能作为答案的条件为满足(b&a_i=b)(a_i)不少于(lceil frac{n}{2} ceil)个。于是可以用(FWT)来统计答案,令(A_k=sum_{i=2}^{n}[a_i==k]),对于(fwtand)

    [FWTAND[A]_i=sum_{j&i=i}A_j ]

    故此情况下可以将答案更新为(max{ card(i) |A_igelceil frac{n}{2} ceil})

    (T)为随机的次数,则总复杂度为(O(Tp(2^p+n)))

    (old{PS:})生成的随机数类型为unsigned int,范围为(0sim 2^{32}-1),如果要得到的随机数为int要先模(n)再强转为int,否则会出现负数!

    #include <bits/stdc++.h>
    #define pb(x) push_back(x)
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> P;
    const int N=3e5+10,INF=1<<30;
    int n,m,p=0,c[N],aa[N],res[62];
    char s[75]; 
    int pc[(1<<15)+10];
    void fwtand(ll *a,int n,int typ){
    	for(int mid=1;mid<n;mid<<=1){
    		for(int r=(mid<<1),j=0;j<n;j+=r){
    			for(int i=0;i<mid;i++){
    				a[i+j]=(a[i+j]+typ*a[i+j+mid]);
    			}
    		}
    	}
    }
    ll ov[N];
    ll a[(1<<15)+10];
    unsigned sd=chrono::system_clock::now().time_since_epoch().count();
    mt19937 rndnum(sd);
    int rnd(int n){
    	unsigned res=rndnum()%n+1;
    	return res;
    }
    int vis[N];
    void f1(){
    	for(int i=1,l=(1<<15);i<l;i++)pc[i]=pc[i>>1]+(i&1);
    	scanf("%d%d%d",&n,&m,&p);
    	for(int i=1;i<=n;i++){
    		//aa[i]=i;
    		vis[i]=0;
    		scanf("%s",s+1);
    		for(int j=1;j<=m;j++){
    			if(s[j]=='1'){ov[i]|=(1ll<<(j-1));}
    		}
    	}
    	int ans=0;
    	for(int o=1;o<=min(200,n);o++){
    		int u=rnd(n);
    		while(vis[u]){
    			u=rnd(n);
    			//assert(u<=n&&u>=1);
    		}
    		vis[u]=1;
    		ll na=ov[u];p=0;
    		for(int i=1;i<=m;i++){
    			if((1ll<<(i-1))&na){c[++p]=i;}
    		}
    		memset(a,0,sizeof(a));
    		for(int i=1;i<=n;i++){
    			ll y=(na&ov[i]),z=0;
    			for(int j=1;j<=p;j++){
    				if((1ll<<(c[j]-1))&y){
    					z|=(1<<(j-1));
    				}
    			}
    			++a[z];
    		}
    		int l=(1<<p);
    		fwtand(a,l,1);
    		for(int i=0;i<l;i++)if(a[i]*2>=n&&pc[i]>ans){
    			ans=pc[i];
    			memset(res,0,sizeof(res));
    			for(int j=1;j<=p;j++)if(i&(1<<(j-1))){
    				res[c[j]]=1;
    			}	
    		}
    	}
    	for(int i=1;i<=m;i++){printf("%d",res[i]);}
    }
    int main(){
    	//int t;
    	//scanf("%d",&t);
    	//while(t--)
    		f1();
    	return 0;
    }
    /*
    3 4 3
    1000
    0110
    1001
    
    */
    
  • 相关阅读:
    Linux命令之vi
    CentOS7 查看IP
    Linux下mysql的命令
    @RequestMapping注解的参数说明
    springboot处理不同域的前端请求
    vue-cli4 取消关闭eslint 校验代码
    springmvc请求乱码
    访问静态资源报404错误
    eclipse创建Maven项目时pom.xml报错
    spring中的xml配置文件里报错
  • 原文地址:https://www.cnblogs.com/bobh/p/15031782.html
Copyright © 2011-2022 走看看