码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces663E. Binary Table

时间:2018-06-21 11:36:35      阅读:194      评论:0      收藏:0      [点我收藏+]

标签:bitset   isp   string   name   attention   double   math.h   情况下   cto   

$n \leq 20,m \leq 100000$的01矩阵,可整行整列01翻转,问最少剩几个1.

一个暴力的做法是枚举$2^n$种行翻转然后$m$列扫一遍。但其实在行翻转情况确定的情况下我们只关心两个东西:某一列在行翻转后剩几个1,以及有几个这样的列。$f(i,j)$--在行翻转$j$的情况下,有$i$个1的有多少列。其实就是与$j$有$i$个位不同的有多少列。可以枚举每一个位置$p$,那么这一位上与$j$不同的状态$f(i-1,j \ \ xor \ \ 2^p)$可以加过来,但要挑去其中$p$已经算过一次的情况,有$f(i-2,j)$这么多种,又要从$f(i-2,j)$中挑去那些$p$这一位算过一次的情况,$f(i-3,j \ \ xor \ \ 2^p)$,如此循环。但这样枚举完每个位置之后,每种好的情况其实算了$i$次,所以$i \times f(i,j)=\sum_{p=0}^{n-1} \sum_{t=1}^{i}(-1)^{t-1}f(i-t,j \ \ xor \ \ (2^p \times (t \mod 2)))$。

这样是$2^nn^3$的,但可以发现$\sum_{p=0}^{n-1}\sum_{t=3}^{i}(-1)^{t-1}f(i-t,j \ \ xor \ \ (2^p \times (t \mod 2)))=(i-2) \times f(i-2,j)$,所以整理一下,$i \times f(i,j)=\sum_{p=0}^{n-1}f(i-1,j \ \ xor \ \ 2^p)+(i-2-n)f(i-2,j)$。少一个$n$。

要再少一个得用FWT。不会。

技术分享图片
 1 //#include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 //#include<math.h>
 5 //#include<set>
 6 //#include<queue>
 7 //#include<bitset>
 8 //#include<vector>
 9 #include<algorithm>
10 #include<stdlib.h>
11 using namespace std;
12 
13 #define LL long long
14 int qread()
15 {
16     char c; int s=0,f=1; while ((c=getchar())<0 || c>9) (c==-) && (f=-1);
17     do s=s*10+c-0; while ((c=getchar())>=0 && c<=9); return s*f;
18 }
19 
20 //Pay attention to ‘-‘ , LL and double of qread!!!!
21 
22 int K,n;
23 #define maxn 1100011
24 int b[maxn],f[22][maxn];
25 
26 int main()
27 {
28     K=qread(); n=qread();
29     {
30         char c;
31         for (int i=0;i<K;i++)
32             for (int j=1;j<=n;j++)
33             {
34                 while ((c=getchar())!=0 && c!=1);
35                 b[j]|=(c-0)<<i;
36             }
37         for (int i=1;i<=n;i++) f[0][b[i]]++;
38     }
39     int T=1<<K,ans=0x3f3f3f3f;
40     for (int i=1;i<=K;i++)
41     {
42         for (int j=0;j<T;j++)
43         {
44             if (i>1) f[i][j]=(i-2-K)*f[i-2][j];
45             for (int k=0;k<K;k++) f[i][j]+=f[i-1][j^(1<<k)];
46             f[i][j]/=i;
47         }
48     }
49     for (int i=0;i<T;i++)
50     {
51         int tmp=0;
52         for (int j=0;j<=K;j++) tmp+=min(j,K-j)*f[j][i];
53         ans=min(ans,tmp);
54     }
55     printf("%d\n",ans);
56     return 0;
57 }
View Code

 

Codeforces663E. Binary Table

标签:bitset   isp   string   name   attention   double   math.h   情况下   cto   

原文地址:https://www.cnblogs.com/Blue233333/p/9206929.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!