CF662C Binary Table题解
CF662C Binary Table
题目描述
有一个 nnn 行 mmm 列的表格,每个元素都是 0/10/10/1 ,每次操作可以选择一行或一列,把 0/10/10/1 翻转,即把 000 换为 111 ,把 111 换为 000 。请问经过若干次操作后,表格中最少有多少个 111 。
输入格式
第一行是两个整数 nnn 和 mmm ( 1⩽n⩽20,1⩽m⩽1051\leqslant n\leqslant 20,1\leqslant m\leqslant 10^51⩽n⩽20,1⩽m⩽105 )之后 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;
}

浙公网安备 33010602011771号