1 条题解

  • 0
    @ 2024-10-27 19:06:05

    题解:

    对于每列,可以将其映射到一个整数,对于列的操作可以使得每列1的最少数量为min(popcount(x),popcount((1<<n)1x))min(popcount(x),popcount((1<<n)-1-x))。考虑对行的操作,对于所有的行操作,也可以用一个整数表示,记cnt[i]cnt[i]为所有列对应的数中i的数量,f[i]f[i]min(popcount(i),popcount((1<<n)1i))min(popcount(i),popcount((1<<n)-1-i)),则对于行操作xx,最终1的数量为cnt[i]f[ix]\sum cnt[i]*f[i \oplus x],注意到i(ix)==xi\oplus(i \oplus x)==x,该式即为cntcntff的异或卷积的x项系数,fwtfwt可以完成本题。

    如题,SOSDP也可以完成本题。

    #define int long long 
    using namespace std;
    using PII=std::pair<int,int>;
    using i64=long long;
    
    constexpr void xorfwt(std::vector<int> &a,int opt=1){
    	int n=a.size();
    	assert(n==1ll<<std::__lg(n));
    	for(int len=2;len<=n;len<<=1){
    		int k=len>>1;
    		for(int i=0;i<n;i+=len){
    			for(int j=0;j<k;j++){
    				auto u=a[i+j],v=a[i+j+k];
    				if(opt==1){
    					a[i+j]=u+v;
    					a[i+j+k]=u-v;
    				}else if(opt==-1){
    					a[i+j]=(u+v)/2;
    					a[i+j+k]=(u-v)/2;
    				}
    			}
    		}
    	}
    }
    void solve(){
    	int n,m;std::cin>>n>>m;
    	std::vector<std::string> g(n);
    	for(int i=0;i<n;i++){
    		std::cin>>g[i];
    	}
    	std::vector<int> cnt(1ll<<n,0),val(1ll<<n);
    	for(int i=0;i<m;i++){
    		int res=0;
    		for(int j=0;j<n;j++){
    			res+=(g[j][i]=='1')*1ll<<j;
    		}
    		cnt[res]++;
    	}
    	for(int i=0;i<1ll<<n;i++){
    		int x=__builtin_popcount(i);
    		int y=__builtin_popcount((1ll<<n)-1-i);
    		val[i]=std::min(x,y);
    	}
    	std::vector<int> f(1ll<<n);
    	xorfwt(cnt,1);xorfwt(val,1);
    	for(int i=0;i<1ll<<n;i++){
    		f[i]=cnt[i]*val[i];
    	}
    	xorfwt(f,-1);	
    	
    	int ans=n*m;
    	for(int x=0;x<1ll<<n;x++){
    		ans=std::min(ans,f[x]);
    	}
    	std::cout<<ans<<'\n';
    }
    
    
    • 1

    信息

    ID
    226
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    (无)
    递交数
    204
    已通过
    4
    上传者