AtCoder Beginner Contest 220 H - Security Camera (折半处理+FWT)
非常巧妙的好题
代码
/*************************************************************************
> File Name: 1.cpp
> Author: Knowledge_llz
> Mail: 925538513@qq.com
> Blog: https://www.cnblogs.com/Knowledge-Pig/
> Created Time: 2021/9/15 18:40:30
************************************************************************/
#include<bits/stdc++.h>
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define LL long long
#define pb push_back
#define fi first
#define se second
#define pr pair<int,int>
#define mk(a,b) make_pair(a,b)
#define endl '\n'
using namespace std;
int n, m, s, a[50][50], d[50];
LL L[1 << 21], R[1 << 21], to[1 << 21], f[1 << 21];
void FWT(){
for(int i = 2; i <= (1 << n - s); i <<= 1){
int len = i >> 1;
for(int j = 0; j < (1 << n - s); j += i)
for(int k = j; k < j + len; ++k){
LL fl = f[k], fr = f[k + len];
f[k] = fl + fr;
f[k + len] = len + fl - fr;
}
}
}
int main(){
ios::sync_with_stdio(false); cin.tie(0);
#ifndef ONLINE_JUDGE
freopen("input.in", "r", stdin);
freopen("output.out","w", stdout);
#endif
cin >> n >> m;
for(int u, v, i = 1; i <= m; ++i){
cin >> u >> v; --u; --v;
a[u][v] = a[v][u] = 1;
d[u] ^= 1; d[v] ^= 1;
}
s = n / 2;
for(int i = 1; i < (1 << s); ++i){
int x = __builtin_ffs(i) - 1;
L[i] = L[i ^ (1 << x)] ^ d[x];
for(int j = 0; j < s; ++j)
if((i & (1 << j)) > 0) L[i] ^= a[j][x];
}
for(int i = 1; i < (1 << n - s); ++i){
int x = __builtin_ffs(i) - 1;
R[i] = R[i ^ (1 << x)] ^ d[x + s];
for(int j = 0; j < n - s; ++j)
if((i & (1 << j)) > 0) R[i] ^= a[j + s][x + s];
}
for(int i = 1; i < (1 << s); ++i){
int x = __builtin_ffs(i) - 1;
to[i] = to[i ^ (1 << x)];
for(int j = s; j < n; ++j) if(a[x][j]) to[i] ^= (1 << j - s);
}
for(int i = 0; i < (1 << n - s); ++i) f[i] = R[i];
FWT();
LL ans = 0;
for(int i = 0; i < (1 << s); ++i){
if(L[i]) ans += f[to[i]];
else ans += (1 << n - s) - f[to[i]];
}
cout << ans << endl;
return 0;
}

浙公网安备 33010602011771号