CF662C Binary Table题解

CF662C Binary Table

题目描述

有一个 nnnmmm 列的表格,每个元素都是 0/10/10/1 ,每次操作可以选择一行或一列,把 0/10/10/1 翻转,即把 000 换为 111 ,把 111 换为 000 。请问经过若干次操作后,表格中最少有多少个 111

输入格式

第一行是两个整数 nnnmmm1⩽n⩽20,1⩽m⩽1051\leqslant n\leqslant 20,1\leqslant m\leqslant 10^51n20,1m105 )之后 nnn 行,每行 mmm 个数字 0/10/10/1 ,注意数字间无空格。

输出格式

一行,一个整数,表示答案。

感谢@AThousandMoon 提供翻译

输入输出样例 #1

输入 #1

3 4
0110
1010
0111

输出 #1

2

思路

FWT即可。

代码见下

#include<bits/stdc++.h> 
using namespace std;
long long n,m,c[2000006],a[2000006],b[2000006],op=1e18+7,s[2000006];
char ch[22][100005];
const long long mod=1e9+7;
void xor1(long long *f,long long x){
    for(int o=2,k=1;o<=n;o*=2,k*=2){
        for(int i=0;i<=n-1;i+=o){
            for(int j=0;j<=k-1;j++){
                f[i+j]=(f[i+j]+f[i+j+k])%mod;
                f[i+j+k]=(f[i+j]-f[i+j+k]-f[i+j+k]+mod*2)%mod;
                f[i+j]=(f[i+j]*x)%mod;
                f[i+j+k]=(f[i+j+k]*x)%mod;
            }
        }
    }
    return ;
}
long long abc(long long a1){
    long long c1=0;
    while(a1!=0){
        c1+=a1%2;
        a1/=2;
    }
    return c1;
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>ch[i][j];
            c[j]+=(ch[i][j]-'0')*(1<<(i-1));
        }
    }
    n=(1<<n);
    for(int i=1;i<=m;i++){
        a[c[i]]++;
    }
    for(int i=1;i<=n-1;i++){
        s[i]=s[i/2]+i%2;
    }
    for(int i=0;i<=n-1;i++){
        b[i]=min(s[i],(long long)log2(n)-s[i]);
    }
    xor1(a,1);
    xor1(b,1);
    for(int i=0;i<=n-1;i++){
        a[i]=(a[i]*b[i])%mod;
    }
    xor1(a,mod/2+1);
    for(int i=0;i<=n-1;i++){
        op=min(op,a[i]);
    }
    cout<<op<<endl;  
	return 0; 	
}
posted @ 2026-02-06 17:14  bz02_2023f2  阅读(2)  评论(0)    收藏  举报  来源