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;
}
posted @ 2021-09-28 13:10  Knowledge-Pig  阅读(19)  评论(0)    收藏  举报