题面

题解

我们会发现,如果单独的一列或一行,它的答案是O1确定的,如果确定了每一行是否变换,那么最后的答案也就简单了许多,

如果确定了行的变换状压下来是x(即x的i位表示第i行是否变换,理解就行),那么每列的状态就要异或x,这没问题吧

接着,其实它的行列是可以交换顺序的,对答案没有影响,状态一定的列的最终贡献都一样,

所以就把状态为 i 的列的数量记为 c[i],方便计算,

然后,提前预处理出列的状态为 i 时单独考虑的答案 f[i](即反转或不反转的最小1数量),方便计算

若枚举行的变换x,那么

注意,xor的逆运算是xor

于是,就转变成了卷积,用FWT就行了,最后枚举x算最小值完事

害怕答案会爆的朋友也可以使用取模,由于最终的答案肯定不会超过1e6,所以你的模数只要超过1e6就没有影响答案。

CODE

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#include<algorithm>
#include<cmath>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#define MAXN (1<<20|5)
#define LL long long
#define lowbit(x) (-(x) & (x))
#define ENDL putchar('\n')
#define rg register
#pragma GCC optimize(2)
//#pragma G++ optimize(3)
//#define int LL
char char_read_before = 1;
inline int read() {
int f = 1,x = 0;char s = char_read_before;
while(s < '0' || s > '9') {if(s == '-') f = -1;s = getchar();}
while(s >= '0' && s <= '9') {x = x * 10 - '0' + s;s = getchar();}
char_read_before = s;return x * f;
}
inline int readone() {
int x = 0;char s = getchar();
while(s < '0' || s > '9') s = getchar();
char_read_before = 1;return s - '0';
}
int zxy = 1000000007; // 用来膜的
int inv2 = (zxy+1)/2;
inline int qm(LL x,int dalao) {return x >= dalao ? qm(x-dalao,dalao):x;}
int n,m,i,j,s,o,k;
inline void DWTXOR(int *s,int m) {
for(int k = m;k > 1;k >>= 1) {
for(int i = 0;i < m;i += k) {
for(int j = i+(k>>1);j < i+k;j ++) {
int s0 = s[j-(k>>1)],s1 = s[j];
s[j] = qm((s0 +0ll+ zxy - s1) , zxy);
s[j-(k>>1)] = qm((s0 +0ll+ s1) , zxy);
}
}
}
return ;
}
inline void IDWTXOR(int *s,int m) {
for(int k = 2;k <= m;k <<= 1) {
for(int i = 0;i < m;i += k) {
for(int j = i+(k>>1);j < i+k;j ++) {
int s0 = s[j-(k>>1)],s1 = s[j];
s[j-(k>>1)] = qm((s0 +0ll+ s1) , zxy) *1ll* inv2 % zxy;
s[j] = qm((s0 +0ll+ zxy - s1) , zxy) *1ll* inv2 % zxy;
}
}
}
return ;
}
inline void DWTOR(int *s,int m) {
for(int k = m;k > 1;k >>= 1) {
for(int i = 0;i < m;i += k) {
for(int j = i+(k>>1);j < i+k;j ++) {
int s0 = s[j-(k>>1)],s1 = s[j];
s[j] = qm((s0 +0ll+ s1) , zxy);
}
}
}
return ;
}
inline void IDWTOR(int *s,int m) {
for(int k = 2;k <= m;k <<= 1) {
for(int i = 0;i < m;i += k) {
for(int j = i+(k>>1);j < i+k;j ++) {
int s0 = s[j-(k>>1)],s1 = s[j];
s[j] = qm((s1 +0ll+ zxy - s0) , zxy);
}
}
}
return ;
}
inline void DWTAND(int *s,int m) {
for(int k = m;k > 1;k >>= 1) {
for(int i = 0;i < m;i += k) {
for(int j = i+(k>>1);j < i+k;j ++) {
LL s0 = s[j-(k>>1)],s1 = s[j];
s[j-(k>>1)] = qm((s0 +0ll+ s1) , zxy);
}
}
}
return ;
}
inline void IDWTAND(int *s,int m) {
for(int k = 2;k <= m;k <<= 1) {
for(int i = 0;i < m;i += k) {
for(int j = i+(k>>1);j < i+k;j ++) {
int s0 = s[j-(k>>1)],s1 = s[j];
s[j-(k>>1)] = qm((s0 +0ll+ zxy - s1) , zxy);
}
}
}
return ;
}
int A[MAXN],B[MAXN],as[MAXN];
int ct[MAXN],a[MAXN];
int main() {
n = read();m = read();
int M = 1<<n;
for(int i = 1;i < M;i ++) {
ct[i] = ct[i ^ lowbit(i)] + 1;
A[i] = min(ct[i],n - ct[i]);
}
for(int i = 0;i < n;i ++) {
for(int j = 1;j <= m;j ++) {
s = readone();
a[j] |= (s<<i);
}
}
for(int i = 1;i <= m;i ++) B[a[i]] ++;
DWTXOR(A,M);DWTXOR(B,M);
for(int i = 0;i < M;i ++) as[i] = A[i] *1ll* B[i] % zxy;
IDWTXOR(as,M);
int ans = 0x7f7f7f7f;
for(int i = 0;i < M;i ++) ans = min(ans,as[i]);
printf("%d\n",ans);
return 0;
}

CF662C Binary Table (快速沃尔什变换FWT)的更多相关文章

  1. [CF662C Binary Table][状压+FWT]

    CF662C Binary Table 一道 FWT 的板子-比较难想就是了 有一个 \(n\) 行 \(m\) 列的表格,每个元素都是 \(0/1\),每次操作可以选择一行或一列,把 \(0/1\) ...

  2. CF662C Binary Table【FWT】

    CF662C Binary Table 题意: 给出一个\(n\times m\)的\(01\)矩阵,每次可以反转一行或者一列,问经过若干次反转之后,最少有多少个\(1\) \(n\le 20, m\ ...

  3. 一个数学不好的菜鸡的快速沃尔什变换(FWT)学习笔记

    一个数学不好的菜鸡的快速沃尔什变换(FWT)学习笔记 曾经某个下午我以为我会了FWT,结果现在一丁点也想不起来了--看来"学"完新东西不经常做题不写博客,就白学了 = = 我没啥智 ...

  4. 快速沃尔什变换FWT

    快速沃尔什变换\(FWT\) 是一种可以快速完成集合卷积的算法. 什么是集合卷积啊? 集合卷积就是在集合运算下的卷积.比如一般而言我们算的卷积都是\(C_i=\sum_{j+k=i}A_j*B_k\) ...

  5. 集合并卷积的三种求法(分治乘法,快速莫比乌斯变换(FMT),快速沃尔什变换(FWT))

    也许更好的阅读体验 本文主要内容是对武汉市第二中学吕凯风同学的论文<集合幂级数的性质与应用及其快速算法>的理解 定义 集合幂级数 为了更方便的研究集合的卷积,引入集合幂级数的概念 集合幂级 ...

  6. 【学习笔鸡】快速沃尔什变换FWT

    [学习笔鸡]快速沃尔什变换FWT OR的FWT 快速解决: \[ C[i]=\sum_{j|k=i} A[j]B[k] \] FWT使得我们 \[ FWT(C)=FWT(A)*FWT(B) \] 其中 ...

  7. 关于快速沃尔什变换(FWT)的一点学习和思考

    最近在学FWT,抽点时间出来把这个算法总结一下. 快速沃尔什变换(Fast Walsh-Hadamard Transform),简称FWT.是快速完成集合卷积运算的一种算法. 主要功能是求:,其中为集 ...

  8. 快速沃尔什变换 FWT 学习笔记【多项式】

    〇.前言 之前看到异或就担心是 FWT,然后才开始想别的. 这次学了 FWT 以后,以后判断应该就很快了吧? 参考资料 FWT 详解 知识点 by neither_nor 集训队论文 2015 集合幂 ...

  9. Codeforces 662C(快速沃尔什变换 FWT)

    感觉快速沃尔什变换和快速傅里叶变换有很大的区别啊orz 不是很明白为什么位运算也可以叫做卷积(或许不应该叫卷积吧) 我是看 http://blog.csdn.net/liangzhaoyang1/ar ...

随机推荐

  1. conda命令的使用,环境安装,创建环境以Anaconda为例

    Anaconda用命令conda创建环境: 安装Anaconda后,用Conda –version查看conda的版本号: Conda create -n name python = x.xx Con ...

  2. ngx_http_fastcgi_module 的那些事

    是什么? 顾名思义,是Nginx用来处理FastCGI的模块.FastCGI是什么?这个以后再讲,可以说的是现在LNMP架构里面,PHP一般是以PHP-CGI的形式在运行,它就是一种FastCGI,我 ...

  3. SQL Server 2008~2019版本序列号/密钥/激活码 汇总

    SQL Server 2019 Enterprise:HMWJ3-KY3J2-NMVD7-KG4JR-X2G8G Strandard:PMBDC-FXVM3-T777P-N4FY8-PKFF4 SQL ...

  4. React + Typescript领域初学者的常见问题和技巧

    React + Typescript领域初学者的常见问题和技巧 创建一个联合类型的常量 Key const NAME = { HOGE: "hoge", FUGA: "f ...

  5. vue大型电商项目尚品汇(后台篇)day04

    昨天太晚就没来得及更新,今天是spu管理界面,这个界面一共有三个界面需要切换,完成了两个界面,而且今天的难度在于最后两个章节,富有一定的逻辑性,当然中间也有很多需要注意的,比如ElementUI的照片 ...

  6. linux-python安装pip

    wget https://bootstrap.pypa.io/get-pip.py --no-check-certificate sudo python3 get-pip.py linux 建立软连接 ...

  7. numpy学习笔记02

    简介 numpy.array() 数组对象,可以表示普通的一维数组,或者二维矩阵,或者任意数据:并且它可以对数组中的数据进行非常高效的运算,如:数据统计.图像处理.线性代数等 numpy 之所以能运行 ...

  8. sort基本用法

    sort 选项 -u --去除重复行 -r --降序排列,默认是升序 -o --由于sort默认是把结果输出到标准输出,所以需要用重定向才能将结果写入文件,形如sort filename > n ...

  9. Linux yum搭建私有仓库

    搭建yum仓库需要两种资源: rpm包 rpm包的元数据(repodata) 搭建好仓库后需要使用三种网络协议共享出来 http或https ftp 范例: 使用http协议搭建私有仓库 (本示例使用 ...

  10. SpringBoot项目启动org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException解决方法

    将Pom文件中的SpringBoot版本调低即可. 我的是调成了2.5.6