CF662C Binary Table 枚举 FWT
题面
洛谷题面 (虽然洛谷最近有点慢)
题解
观察到行列的数据范围相差悬殊,而且行的数量仅有20,完全可以支持枚举,因此我们考虑枚举哪些行会翻转。
对于第i列,我们将它代表的01串提取出来,表示为\(v[i]\),
然后我们假设有第0列,其中的第i行如果是1,表示这行将会翻转。
那么可以发现,执行完对行的操作时,每一列的状态为\(x = v[i] \oplus v[0]\),此时我们只需要考虑对列的操作,令\(cnt[i]\)表示状态为\(i\)时01串中1的个数。
显然为了使得1的个数尽可能少,对于状态为\(x\)的列,产生的贡献为\(s[x] = min(cnt[x], n - cnt[x])\)
令\(ans[b]\)表示\(v[0] = b\)时的最优解。
那么有
\]
考虑换一种枚举方式,我们枚举\(s[i]\),然后就只需要再找到使得\(v[j] \oplus b = i\)的\(j\)有多少个就可以快速算出贡献了。
\(v[j] \oplus b = i \Longrightarrow v[j] = i \oplus b\)
因此我们只需要找到有多少个\(v[j] = i \oplus b\)即可,令\(p[i]\)表示有多少列的状态为\(i\),
那么我们要求的个数即为\(p[i \oplus b]\)
因此答案就是:
\]
观察到\(i \oplus i \oplus b = b\),是一个定值。
因此上式等效于
\]
直接上FWT即可
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define LL long long
#define AC 22
#define ac 100100
#define N 1050000
int n, m, maxn;
LL s[N], p[N], ans[N];
char ss[AC][ac];
inline void upmin(LL &a, LL b){if(b < a) a = b;}
inline int cal(int x)
{
int rnt = 0;
while(x) rnt += x & 1, x >>= 1;
return rnt;
}
void pre()
{
scanf("%d%d", &n, &m), maxn = 1 << n;
for(R i = 1; i <= n; i ++) scanf("%s", ss[i] + 1);
for(R i = 0; i <= maxn; i ++) s[i] = min(cal(i), n - cal(i));
for(R i = 1; i <= m; i ++)
{
int x = 0;
for(R j = 1; j <= n; j ++) x <<= 1, x += (ss[j][i] == '1');
++ p[x];
}
/* for(R i = 0; i < maxn; i ++) printf("%lld ", s[i]);
printf("\n");
for(R i = 0; i < maxn; i ++) printf("%lld ", p[i]);
printf("\n"); */
}
void fwt(LL *A, int opt)
{
for(R i = 2; i <= maxn; i <<= 1)
for(R r = i >> 1, j = 0; j < maxn; j += i)
for(R k = j; k < j + r; k ++)
{
LL x = A[k], y = A[k + r];
A[k] = x + y, A[k + r] = x - y;
if(opt < 0) A[k] >>= 1, A[k + r] >>= 1;
}
}
void work()
{
fwt(s, 1), fwt(p, 1);
for(R i = 0; i < maxn; i ++) ans[i] = s[i] * p[i];
fwt(ans, -1);
LL rnt = n * m;
for(R i = 0; i < maxn; i ++) upmin(rnt, ans[i]);
printf("%lld\n", rnt);
}
int main()
{
// freopen("in.in", "r", stdin);
pre();
work();
// fclose(stdin);
return 0;
}
CF662C Binary Table 枚举 FWT的更多相关文章
- CF662C Binary Table【FWT】
CF662C Binary Table 题意: 给出一个\(n\times m\)的\(01\)矩阵,每次可以反转一行或者一列,问经过若干次反转之后,最少有多少个\(1\) \(n\le 20, m\ ...
- CF662C Binary Table (FWT板题)
复习了一发FWT,发现还挺简单的... 没时间写了,就放一个博客吧:Great_Influence 的博客 注意这一句ans[i]=∑j⊗k=if[j]∗dp[k]ans[i]= ∑_{j⊗k=i} ...
- [CF662C] Binary Table(FWT)
题意: https://www.cnblogs.com/cjyyb/p/9065801.html 题解:
- [CF662C Binary Table][状压+FWT]
CF662C Binary Table 一道 FWT 的板子-比较难想就是了 有一个 \(n\) 行 \(m\) 列的表格,每个元素都是 \(0/1\),每次操作可以选择一行或一列,把 \(0/1\) ...
- 【CF662C】Binary Table(FWT)
[CF662C]Binary Table(FWT) 题面 洛谷 CF 翻译: 有一个\(n*m\)的表格(\(n<=20,m<=10^5\)), 每个表格里面有一个\(0/1\), 每次可 ...
- CF662C Binary Table FWT
传送门 \(N \leq 20\)很小诶 一个暴力的思路是枚举行的翻转状态然后在列上贪心 复杂度为\(O(2^NM)\)显然过不去 考虑到可能有若干列的初始状态是一样的,那么在任意反转之后他们贪心的策 ...
- CF662C Binary Table 【状压 + FWT】
题目链接 CF662C 题解 行比较少,容易想到将每一列的状态压缩 在行操作固定的情况下,容易发现每一列的操作就是翻转\(0\)和\(1\),要取最小方案,方案唯一 所以我们只需求出每一种操作的答案 ...
- CF662C Binary Table (快速沃尔什变换FWT)
题面 题解 我们会发现,如果单独的一列或一行,它的答案是O1确定的,如果确定了每一行是否变换,那么最后的答案也就简单了许多, 如果确定了行的变换状压下来是x(即x的i位表示第i行是否变换,理解就行), ...
- Codeforces663E Binary Table(FWT)
题目 Source http://codeforces.com/contest/663/problem/E Description You are given a table consisting o ...
随机推荐
- 洛谷P1514 引水入城
洛谷P1514 引水入城 原题链接 一道好题...细节真多 第一次提交90分,然后就GG了,不知从何改起 其实比较简单吧... 首先,一个点的水流向最后一排,一定可以形成一个区间. 不行的话肯定GG ...
- 【mysql经典题目】行转列
参考:http://www.cnblogs.com/h07061108/p/mysql_questions.html#3806338 实现如下效果 CREATE TABLE IF NOT EXISTS ...
- linux设置定时任务调用接口
1.设置目录 cd /var/spool/cron 2.编辑文件(当前登录用户,不一定是root) vim root 3.添加内容 0 0 * * * wget http://192.144.141. ...
- Python爬虫:爬取美拍小姐姐视频
最近在写一个应用,需要收集微博上一些热门的视频,像这些小视频一般都来自秒拍,微拍,美拍和新浪视频,而且没有下载的选项,所以只能动脑想想办法了. 第一步 分析网页源码. 例如:http://video. ...
- linux常用的查看设备的命令
系统 # uname -a # 查看内核/操作系统/CPU信息 # head -n 1 /etc/issue # 查看操作系统版本 # cat /proc/cpuinfo # 查看CPU信息 # ...
- OpenLDAP备份和恢复
OpenLDAP中数据备份一般分为二种: 1)通过slapcat 指令进行备份 2)通过phpLDAPadmin控制台进行备份 备份方式1: 1)slapcat -v -l openldap-back ...
- Git + Gerrit 操作备忘
Git review 作用 可以用来提交代码审核到Gerrit 安装 使用pip 安装 git-review 插件,执行 sudo -H pip install git-review 使用示例 可以参 ...
- mysql 5.5 zip配置安装
1.解压2.创建option文件 --defaults-file=../my.ini [mysql] # 设置mysql客户端默认字符集 default-character-set=utf8 [mys ...
- [python]序列的重复操作符
当你需要需要一个序列的多份拷贝时,重复操作符非常有用,它的语法如下: sequence * copies_int In [1]: a = [1,2,3,4] In [2]: a * 5 Out[2]: ...
- 使用Node.js 搭建http服务器 http-server 模块
1. 安装 http-server 模块 npm install http-server -g 全局安装 2.在需要的文件夹 启动 http-server 默认的端口是8080 可以使 ...