zoukankan      html  css  js  c++  java
  • 【CF662C】Binary Table 按位处理

    【CF662C】Binary Table

    题意:给你一个$n imes m$的01网格,你可以进行任意次操作,每次操作是将一行或一列的数都取反,问你最多可以得到多少个1?

    $nle 20,mle 10^5$

    题解:我也不知道叫啥了,说状压也不对,说fwt也不太对,就叫按位处理得了。

    显然有$O(2^nm)$暴力,先枚举每行是否取反,然后枚举每列,如果0多就取反,否则不取。

    但我们发现我们完全可以将本质相同的列一起处理,什么叫本质相同的列呢?假如我们对每行是否取反的状态为S,则所有$xor S$中1的个数相同的列我们都认为是相同的。那么现在问题就变成了对于所有S,$xor S$中1的个数为i的列的个数是多少。我们可以设f[S][i]表示这个状态,初始时f[T][0]++(T是某一列的状态)。然后我们枚举二进制的每一位是否取反,再从大到小枚举1的个数,进行转移即可。最后的答案就是$max{sumlimits_{i=0}^n f[S][i] imes max{i,n-i}}$。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    int n,m,ans;
    char s[21][100001];
    int f[21][(1<<20)+1];
    int main()
    {
    	scanf("%d%d",&n,&m),ans=1<<30;
    	int i,j,k;
    	for(i=0;i<n;i++)	scanf("%s",s[i]);
    	for(i=0;i<m;i++)
    	{
    		int tmp=0;
    		for(j=0;j<n;j++)	if(s[j][i]=='1')	tmp|=1<<j;
    		f[0][tmp]++;
    	}
    	for(i=0;i<n;i++)	for(j=n;j;j--)	for(k=0;k<(1<<n);k++)	f[j][k]+=f[j-1][k^(1<<i)];
    	for(k=0;k<(1<<n);k++)
    	{
    		int tmp=0;
    		for(i=0;i<=n;i++)	tmp+=min(i,n-i)*f[i][k];
    		ans=min(ans,tmp);
    	}
    	printf("%d",ans);
    	return 0;
    }
  • 相关阅读:
    python 汇总
    python 异常处理、文件常用操作
    python类中super()和__init__()的区别
    百度搜索结果爬虫
    BS4爬虫实例应用-CISP
    Java类WebServer及中间件拿webshell方法总结
    建模分析之机器学习算法(附python&R代码)
    [原创]代理转发工具汇总分析
    代码审计之文件操作
    PHP自带防SQL攻击函数区别
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/8594527.html
Copyright © 2011-2022 走看看