CF662C Binary Table
Posted Jozky86
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF662C Binary Table相关的知识,希望对你有一定的参考价值。
题意:
有一个 n 行 m 列的表格,每个元素都是 0/1 ,每次操作可以选择一行或一列,把 0/1 翻转,即把 0 换为 1 ,把 1 换为 0 。请问经过若干次操作后,表格中最少有多少个 1
n<=20,m<=1e5
题解:
参考
洛谷题解第一篇,讲的太详细了
因为行很小(n<=20),列很大(m<=1e5),因为我们可以考虑枚举反转了哪些行。设X表示翻转了哪些行(X是一个整数,其二进制表示翻转的状态)
对于任意一列,设第i列的状态为
S
i
S_i
Si,也是其二进制表示该列的状态
现在开始考虑每一列都变成什么样子:
设第i列翻转后变成了状态
Y
i
Y_i
Yi,显然有
Y
i
=
S
i
⨁
X
Y_i=S_i \\bigoplus X
Yi=Si⨁X
对于一个相同的X(即一个行翻转方案),最优答案1的个数是唯一的,而X最多只有
2
20
=
1048576
2^20=1048576
220=1048576,也就是我们可以直接枚举X
因为每一列都是相互独立的,为了让表格中1最少,对于每一列翻转到最少个1位置,设状态为i时经过翻转这个二进制最少有
F
i
F_i
Fi个1
比如n=3,
(
3
)
10
=
(
011
)
2
(3)_10=(011)_2
(3)10=(011)2,翻转后为
(
100
)
2
(100)_2
(100)2
所以
F
3
=
1
F_3=1
F3=1
答案就是
∑
i
=
1
m
F
X
⨁
S
i
\\sum_i=1^mF_\\X \\bigoplus S_i\\
∑i=1mFX⨁Si
我们枚举所有X,再枚举每一列状态的S,总复杂度是
O
(
2
n
m
)
O(2^nm)
O(2nm),还是不行
继续对式子优化:我们枚举
Y
i
=
S
i
⨁
X
Y_i=Si \\bigoplus X
Yi=Si⨁X
式子为:
∑
i
=
1
m
∑
Y
=
0
2
n
[
Y
=
=
S
i
⨁
X
]
F
Y
\\sum_i=1^m\\sum_Y=0^2^n[Y==S_i \\bigoplus X]F_Y
i=1∑mY=0∑2n[Y==Si⨁X]FY
我们试着换掉第一个枚举m的
∑
\\sum
∑,设所有列中有
Q
i
Q_i
Qi列的状态为i,相当于用桶来存
这样就可以得到:
∑
S
=
0
2
n
∑
Y
=
0
2
n
[
Y
=
=
S
⨁
X
]
F
Y
×
Q
S
\\sum_S=0^2^n\\sum_Y=0^2^n[Y==S \\bigoplus X]F_Y×Q_S
S=0∑2nY=0∑2n[Y==S⨁X]FY×QS
这样枚举每个S,不用再枚举[1,m]
不过还是没啥卵用,因为此时复杂度是
O
(
2
2
n
)
O(2^2n)
O(22n),好像还更差了,但与m无关了
此时这个式子就有些猫腻了
∑
S
=
0
2
n
∑
Y
=
0
2
n
[
Y
=
=
S
⨁
X
]
F
Y
×
Q
S
\\sum_S=0^2^n\\sum_Y=0^2^n[Y== S \\bigoplus X]F_Y×Q_S
S=0∑2nY=0∑2n[Y==S⨁X]FY×QS
⇔
∑
S
=
0
2
n
∑
Y
=
0
2
n
[
Y
⨁
S
=
X
]
F
Y
×
Q
S
⇔\\sum_S=0^2^n\\sum_Y=0^2^n[Y \\bigoplus S= X]F_Y×Q_S
⇔S=0∑2nY=0∑2n[Y⨁S=X]FY×QS
⇔
∑
Y
⨁
S
F
Y
×
Q
S
⇔\\sum_Y \\bigoplus SF_Y×Q_S
⇔Y⨁S∑FY×QS
设
A
N
S
[
X
]
=
∑
Y
⨁
S
=
X
F
Y
×
Q
S
ANS[X]=\\sum_Y \\bigoplus S=XF_Y×Q_S
ANS[X]=∑Y⨁S=XFY×QS
这这。。不就是FWT吗?答案不就是F和Q的xor卷积,这样复杂度就变成了
O
(
2
n
∗
l
o
g
(
2
n
)
)
=
O
(
2
n
∗
n
)
O(2^n*log(2^n))=O(2^n*n)
O(2n∗log(2n))=O(2n∗n),完美解决
代码:
#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
void read();
template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar)
x= 0;
char c= getchar();
bool flag= 0;
while (c < '0' || c > '9')
flag|= (c == '-'), c= getchar();
while (c >= '0' && c <= '9')
x= (x << 3CF662C Binary Table