• CF662C Binary Table


    • 链接
    • (nleq 20),枚举列状态,然后(O(m))贪心一下。
    • (O(2^nm)),显然过不去。考虑优化一下。
    • (f_i)表示状态(i)的出现次数,(g_i)表示(i)状态的贡献,设修改状态(k)的答案是(h_k),则

    [h_k=sum_{k xor i =j}f_i*g_j ]

    • 也就是本来(i)的个数,现在通过(k)变成了(j),乘上(j)的贡献。
    • (fwt)卷一下就可以了。
    #include<bits/stdc++.h>
    #define R register int
    #define ll long long
    using namespace std;
    const int N=100001;
    const int M=1248576;
    int n,m,len,x;ll ans,f[M],g[M];
    char S[23][N];
    int gi(){
        R x=0,k=1;char c=getchar();
        while(c!='-'&&(c<'0'||c>'9'))c=getchar();
        if(c=='-')k=-1,c=getchar();
        while(c<='9'&&c>='0')x=(x<<3)+(x<<1)+c-'0',c=getchar();
        return x*k;
    }
    void fwt(ll *A,R op){
    	for(R i=1;i<len;i<<=1)
    		for(R p=(i<<1),j=0;j<len;j+=p)
    			for(R k=0;k<i;++k){
    				ll x=A[j+k],y=A[j+k+i];
    				A[j+k]=(x+y)/op,A[j+k+i]=(x-y)/op;
    			}
    }
    int main(){
    	n=gi(),m=gi(),len=(1<<n);
    	for(R i=1;i<=n;++i)scanf("%s",S[i]+1);
    	for(R i=1;i<=m;++i){
    		x=0;
    		for(R j=1;j<=n;++j)
    			x=(x<<1)+S[j][i]-'0';
    		f[x]++;
    	}
    	for(R i=1;i<len;++i)g[i]=g[i>>1]+(i&1);
    	for(R i=1;i<len;++i)g[i]=min(g[i],n-g[i]);
    	fwt(f,1),fwt(g,1);
    	for(R i=0;i<len;++i)f[i]*=g[i];
    	fwt(f,2),ans=f[0];
    	for(R i=1;i<len;++i)ans=min(ans,f[i]);
    	cout<<ans<<endl;
    	return 0;
    }
    
    
  • 相关阅读:
    Android开发学习之路--Content Provider之初体验
    [NOI2005] 维修数列
    递归算法对完全二叉树的前序遍历
    非递归算法对完全二叉树的前序遍历
    java中的多态
    poj1088滑雪
    在网页中插入flash
    如何采用批处理文件安装一个.dll文件,并且注册
    结构体指针和数组理解
    完全二叉树
  • 原文地址:https://www.cnblogs.com/Tyher/p/10039707.html
Copyright © 2020-2023  润新知