CodeForces 663E - Binary Table FWT
来源:互联网 发布:php admin value 编辑:程序博客网 时间:2024/05/17 06:18
【题目链接】见这里
【题意】
给出一个n(n≤20)行m(m≤105)列的01矩阵。每次操作可以将某一行取反或者将某一列取反。要求操作后的矩阵中的1的个数最少,求最小个数。
【解题思路】
由于行比较少,我们考虑状压。状压每一列的状态,sta第i位为1,代表第i行为1,否则为0。现在我们有一个F(sta) 代表状态为sta的时候的列的数量。考虑一下我们操作了哪些行?对于一个状态mask,第i位为一代表我们翻转了第i行,否则代表没翻转。
考虑一个mask对sta的影响,显然是sta ^ mask。不妨设为res。
然后对于一个res,我们不妨预处理一个G(res)代表res这样的一列翻转之后和翻转之前1的个数的最小值。
但是m有10^5直接做是不可能的,我们考虑如何优化?
构造一个函数H(mask),表示操作为mask的时候1的个数。不难想到
我们改写一下这个等式:
这样难道不就是做一个异或卷积和就行了吗?所以我们用FWT优化即可。
【AC代码】
////Created by BLUEBUFF 2016/1/10//Copyright (c) 2016 BLUEBUFF.All Rights Reserved//#pragma comment(linker,"/STACK:102400000,102400000")#include <ext/pb_ds/assoc_container.hpp>#include <ext/pb_ds/tree_policy.hpp>#include <ext/pb_ds/hash_policy.hpp>#include <set>#include <map>#include <queue>#include <stack>#include <cmath>#include <cstdio>#include <time.h>#include <cstdlib>#include <cstring>#include <complex>#include <sstream> //isstringstream#include <iostream>#include <algorithm>using namespace std;//using namespace __gnu_pbds;typedef long long LL;typedef pair<int, LL> pp;#define REP1(i, a, b) for(int i = a; i < b; i++)#define REP2(i, a, b) for(int i = a; i <= b; i++)#define REP3(i, a, b) for(int i = a; i >= b; i--)#define CLR(a, b) memset(a, b, sizeof(a))#define MP(x, y) make_pair(x,y)template <class T1, class T2>inline void getmax(T1 &a, T2 b) { if (b>a)a = b; }template <class T1, class T2>inline void getmin(T1 &a, T2 b) { if (b<a)a = b; }const int maxn = 20;const int maxm = 1e5+5;const int maxs = 10;const int maxp = 1e3 + 10;const int INF = 1e9;const int UNF = -1e9;const int mod = 1e9 + 7;const int rev = (mod + 1) >> 1; // FWTconst double PI = acos(-1);//headint A[maxm], n , m;char s[maxm];int F[1<<maxn], G[1<<maxn];void FWT(int a[],int n){ for(int d=1;d<n;d<<=1) for(int m=d<<1,i=0;i<n;i+=m) for(int j=0;j<d;j++) { int x=a[i+j],y=a[i+j+d]; a[i+j]=(x+y)%mod,a[i+j+d]=(x-y+mod)%mod; //xor:a[i+j]=x+y,a[i+j+d]=(x-y+mod)%mod; //and:a[i+j]=x+y; //or:a[i+j+d]=x+y; }}void UFWT(int a[],int n){ for(int d=1;d<n;d<<=1) for(int m=d<<1,i=0;i<n;i+=m) for(int j=0;j<d;j++) { int x=a[i+j],y=a[i+j+d]; a[i+j]=1LL*(x+y)*rev%mod,a[i+j+d]=(1LL*(x-y)*rev%mod+mod)%mod; //xor:a[i+j]=(x+y)/2,a[i+j+d]=(x-y)/2; //and:a[i+j]=x-y; //or:a[i+j+d]=y-x; }}void solve(int a[],int b[],int n){ FWT(a,n); FWT(b,n); for(int i=0;i<n;i++) a[i]=1LL*a[i]*b[i]%mod; UFWT(a,n);}int main(){ cin >> n >> m; for(int i = 0; i < n; i++){ scanf("%s", s); for(int j = 0; j < m; j++){ A[j] = A[j] << 1 | (s[j] - '0'); } } for(int i = 0; i < m; i++) F[A[i]] += 1; for(int i = 0; i < (1<<n); i++){ int t = __builtin_popcount(i); G[i] = min(t, n - t); } solve(F, G, 1<<n); int ans = n * m; for(int i = 0; i < 1 << n; i++){ ans = min(ans , (int) F[i]); } cout << ans << endl;}
0 0
- CodeForces 663E - Binary Table FWT
- [FWT] Codeforces 663E. Binary Table
- [FWT] Codeforces663E .Binary Table
- [ FWT ] Codeforces663E Binary Table
- Codeforces 662C Binary Table 快速沃尔什变换(FWT)
- Codeforces 662C Binary Table FWT 快速沃尔什变换
- codeforces E Square Table
- Codeforces Round #347 (Div. 1) E. Binary Table ★ ★ ★
- Codeforces 651E:Table Compression
- Codeforces 417E Square Table(随机算法)
- Codeforces 417E Square Table(随机算法)
- Codeforces 40E Number Table (计数)
- Codeforces 651E Table Compression 拓扑序
- [杂题 组合] Codeforces #40E. Number Table
- CodeForces 400E Inna and Binary Logic
- 【Codeforces Round #170】Codeforces 277E Binary Tree on Plane
- FWT
- FWT
- HBase入门-优化技巧
- java之yield(),sleep(),wait()区别详解-备忘笔记
- Ajax和Json的总结
- 【Hibernate】多对多映射
- nginx+keepalived主辅切换
- CodeForces 663E - Binary Table FWT
- vs2015源文件创建代码自动版权声明注释
- 使用bat命令得到文件名列表
- HBase入门-存储
- node.js 功能点树形结构操作
- eclipse怎样配置hibernate和反向生成实体类(mysql数据库)
- x264 for Android 的编译
- 利用 MSDaRT 轻松解决 windows7 系统问题
- reactjs 选项卡 初学