zoukankan      html  css  js  c++  java
  • [CF662C]Binary Table

    luogu

    题意

    你有一个(n*m)(01)矩阵。你可以把任意一行或者一列的(01)取反。求矩阵中最少的(1)的数量。
    (nle20,mle10^5)

    sol

    很自然地有一个(O(2^nm))的暴力:枚举横行的取反情况,然后纵列就取(01)数量较少的一者。
    我们记状态(x)在原矩阵中的出现次数为(a[x]),状态中(01)较少一者的数量为(b[x])
    会发现当最终的取反状态为(i)时,会有(ans_i=sum_{jotimes k=i}a_j*b_k)
    就是一个异或卷积。FWT即可。

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int gi(){
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    #define ll long long
    const int N = 1<<20;
    const int M = 1e5+5;
    int n,m,len;ll a[N],b[N];char s[20][M];
    void fwt(ll *P,int opt){
    	for (int i=1;i<len;i<<=1)
    		for (int p=i<<1,j=0;j<len;j+=p)
    			for (int k=0;k<i;++k){
    				ll x=P[j+k],y=P[j+k+i];
    				P[j+k]=(x+y)/opt;P[j+k+i]=(x-y)/opt;
    			}
    }
    int main(){
    	n=gi();m=gi();len=1<<n;
    	for (int i=0;i<n;++i) scanf("%s",s[i]+1);
    	for (int i=1;i<=m;++i){
    		int x=0;
    		for (int j=0;j<n;++j) x=(x<<1)+s[j][i]-'0';
    		++a[x];
    	}
    	for (int i=1;i<len;++i) b[i]=b[i>>1]+(i&1);
    	for (int i=1;i<len;++i) b[i]=min(b[i],n-b[i]);
    	fwt(a,1);fwt(b,1);
    	for (int i=0;i<len;++i) a[i]*=b[i];
    	fwt(a,2);
    	ll ans=a[0];
    	for (int i=1;i<len;++i) ans=min(ans,a[i]);
    	printf("%I64d
    ",ans);return 0;
    }
    
  • 相关阅读:
    SQL LOADER使用
    固定资产新增接口
    固定资产的调整分配接口
    固定资产的完全报废接口
    固定资产更新接口
    详解EBS接口开发之库存事务处理采购接收和退货
    物料分类新增&更新
    物料REVISION控制
    供应商导入的API补充(详解EBS接口开发之供应商导入)
    PostgreSQL经常使用函数
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9068280.html
Copyright © 2011-2022 走看看