====== FWT刷题 ======
==== CF662C ====
题意:给定一个n*m的01矩阵,可以取反若干次任意行或列,问若干次操作之后1最少是多少。
数据范围:$n\leq 20,m\leq 100000$
题解:n的范围很小,我们可以考虑二进制枚举行的取反策略,假设行的翻转策略为S,那么这道题目的答案就是$\sum_{i=1}^m min(f(S\oplus a_i),n-f(S\oplus a_i))$,f函数为这一列1的个数。
那么我们假设$g(i)=min(f(i),n-f(i))$,那么原式就可以改写为$\sum_{j,i\oplus S = j}g(j)\times f(i)$,按照异或的性质,可以直接改写为
$\sum_{j,i\oplus j = S}g(j)\times f(i)$
那么好了,接下来我们就可以轻松的用fwt解决这道题目了。
#include
using namespace std;
const int V = 1<<20;
const int N = 22;
const int M = 100005;
int n,a[M];
long long dp[V],cnt[V];
char s[N][M];
int calc(int x) {
int ans = 0;
while (x) {
ans+=(x&1);
x>>=1;
}
return ans;
}
void FWT(long long *src,int len) {
for (int sz = 2;sz <= len; sz<<=1) {
int step = sz>>1;
for (int i = 0;i < len;i+=sz) {
for (int j = i;j < i+step;j++) {
long long a = src[j],b = src[j+step];
src[j] = a+b;
src[j+step] = a-b;
}
}
}
}
void IFWT(long long *src,int len) {
for (int sz = 2;sz <= len;sz <<= 1) {
int step = sz >> 1;
for (int i = 0;i>1;
src[j+step] = (a-b)>>1;
}
}
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for (int i = 0;i
\\
==== CF914G ====
==== HDU5909 ====
给定一个n个点的树,定义一个树的权值是书上所有点点权的异或值,问这个树权值为$[0,m)$的子图分别有多少个。
直接树形dp,然后用fwt加速计算就行惹
#include
#include
#include
#include
using namespace std;
typedef long long ll;
int inv_2;
const int N = 1<<10;
const int mod = 1e9+7;
int quikc_pow(int x,int y)
{
int res = 1;
while(y)
{
if(y&1)res = (ll)res*x%mod;
x = (ll)x*x%mod;
y>>=1;
}
return res;
}
struct E
{int next,to;}e[N<<1];
int head[N],tot,d,n,m;
void add(int x,int y)
{
e[++tot].to = y;e[tot].next = head[x];head[x] = tot;
e[++tot].to = x;e[tot].next = head[y];head[y] = tot;
}
void FWT(int a[],int n,int type)
{
if(n==1)return ;
int hl = n>>1;
for(int i = 0;i>1,type);
FWT(a+hl,n>>1,type);
}
struct data
{
int a[N];
data(){memset(a,0,sizeof(a));}
int& operator[](int x){return a[x];}
void FWT(int type)
{::FWT(a,d,type);}
friend data operator +(data a,data b)
{
data res;
for(int i = 0;i< d;i++)
res[i]=(a[i]+b[i])%mod;
return res;
}
friend data operator *(data a,data b)
{
data res;
for(int i = 0;i
\\
==== HDU5823 ====
==== HDU6057 ====