CF662C Binary Table

Posted Jozky86

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF662C Binary Table相关的知识,希望对你有一定的参考价值。

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=SiX
对于一个相同的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=1mFXSi
我们枚举所有X,再枚举每一列状态的S,总复杂度是 O ( 2 n m ) O(2^nm) O(2nm),还是不行
继续对式子优化:我们枚举 Y i = S i ⨁ X Y_i=Si \\bigoplus X Yi=SiX
式子为: ∑ 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=1mY=02n[Y==SiX]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=02nY=02n[Y==SX]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=02nY=02n[Y==SX]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=02nY=02n[YS=X]FY×QS
⇔ ∑ Y ⨁ S F Y × Q S ⇔\\sum_Y \\bigoplus SF_Y×Q_S YSFY×QS
A N S [ X ] = ∑ Y ⨁ S = X F Y × Q S ANS[X]=\\sum_Y \\bigoplus S=XF_Y×Q_S ANS[X]=YS=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(2nlog(2n))=O(2nn),完美解决

代码:

#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 << 3) + (x << 1以上是关于CF662C Binary Table的主要内容,如果未能解决你的问题,请参考以下文章

CF662C Binary Table

CF662C Binary Table

「CF662C」 Binary Table

CF662C Binary Table

CF662C Binary Table(FWT)

CF662C Binary TableFWT