博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Codeforces #662C Binary Table
阅读量:6341 次
发布时间:2019-06-22

本文共 1331 字,大约阅读时间需要 4 分钟。

听说这是一道$ Tourist$现场没出的题

题意:

给定$n*m的 01$矩阵,可以任意反转一行/列($0$变$1$,$1$变$0$),求最少$ 1$的数量

$ n<=20 \ m<=100000$


$ Solution$

考虑暴力

枚举每一行反转/不反转

预处理$ g(s)$表示某状态为$ s$的列的最少$ 1$的数量

显然$ g(s)=min(popcount(s),n-popcount(s))$

枚举每行是否反转之后直接$ O(m)$计算即可

时间复杂度$ O(2^n m)$,无法通过这题

 

容易发现瓶颈在于暴力枚举行状态之后无法快速计算答案

我们令$ f(s)$表示列状态为$ s$的列的出现次数,$ F(s)$表示行反转状态为$ s$的时候的答案

转移有$ F(s)=\sum\limits_{i=0}^{2^n-1}f(i)g(i \ xor \ s)$

由于$ i \ xor \ i \  xor \  s = s$

所以可以化简为$ F(s)=\sum\limits_{i \ xor \ j =s}f(i)g(j)$

是一个$ FWT$卷积的形式

直接$ FWT$优化

时间复杂度:$ O(nm+2^n n)$

注意$ FWT$过程中可能要开$ long \ long$


$ my \ code:$

#include
#include
#include
#include
#include
#include
#include
#define rt register int#define ll long longusing namespace std;inline ll read(){ ll x = 0; char zf = 1; char ch = getchar(); while (ch != '-' && !isdigit(ch)) ch = getchar(); if (ch == '-') zf = -1, ch = getchar(); while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar(); return x * zf;}void write(ll y){ if(y<0)putchar('-'),y=-y;if(y>9)write(y/10);putchar(y%10+48);}void writeln(const ll y){write(y);putchar('\n');}int i,j,k,m,n,x,y,z,cnt,invn;void fwt(int n,ll *a,int fla){ for(rt i=1;i
<<=1) for(rt j=0;j
<<1) for(rt k=0;k

 

转载于:https://www.cnblogs.com/DreamlessDreams/p/10038268.html

你可能感兴趣的文章
Oracle12C 开启关闭em
查看>>
pfSense端口回流的设置
查看>>
条件测试&&自定义退出状态码小练习
查看>>
Android 懒加载优化
查看>>
collections系列功能介绍
查看>>
LEMP:Nginx+mysql+php+xcache基于phpmyadmin管理
查看>>
可任意操作nf_conntrack的nf_sockopt_ops
查看>>
编写python调用dubbo接口hessian协议的例子
查看>>
Centos6.8系统安装代码杀毒软件:ClamAV
查看>>
RedHat5.4使用Centsoyum源
查看>>
linux>>网络客户端命令
查看>>
湖北松滋历史上十二大李氏家族
查看>>
VS2008下载地址和版本破解
查看>>
C# 视频监控系列(12):H264播放器——播放录像文件
查看>>
Silverlight 5 beta新特性探索系列:4.Silverlight 5 beta中鼠标双击/鼠标多重点击的实现...
查看>>
PPP协议
查看>>
linux内核3.0rc发布了
查看>>
脚本调用
查看>>
C++的变量作用域
查看>>
telnet mail
查看>>