CF383E Vowels

发布时间 2023-08-31 19:56:30作者: 徐子洋

题目链接

拿到这题,看到求答案的方式:“平方的异或和”。这是就能想到可能有两种方式统计答案:

  • 直接按照他所说的去算。

    算出每一种情况下的数量平方再取个异或和。

  • 拆贡献

    既然是平方,就无异于点对数,故而可以两两之间统计贡献。

但是这道题拆贡献很难做(或许是没法做),故而考虑直接去算。

我们发现直接统计合法数量很难,故而我们统计不合法数量。我们发现不合法数量必须要求是当前集合补集的子集。我们采用高维前缀和求和即可。

时间复杂度 \(O(2^c \times c)\),其中 \(c=24\),表示字母数量。

点击查看代码
#include <bits/stdc++.h>
#define L(i, a, b) for(int i = a; i <= b; i++)
#define R(i, a, b) for(int i = a; i >= b; i--)
using namespace std;
const int N = 1e4 + 10;
int n, U, ans, f[1 << 24];
int main(){
    scanf("%d", &n), U = (1 << 24) - 1;
    L(i, 1, n){
        int s = 0; char ch;
        L(j, 1, 3) scanf(" %c", &ch), s |= (1 << ch - 'a');
        f[s]++;
    }
    L(i, 0, 23) L(s, 0, U) if(s & (1 << i))
        f[s] += f[s ^ (1 << i)];
    L(s, 0, U) ans ^= (n - f[U ^ s]) * (n - f[U ^ s]);
    printf("%d\n", ans);
    return 0;
}