题意
给定 $n$ 个元素,每个元素是一个六元组,求有多少对元素满足相同位恰好有 $k$ 个。
$n\leq10^5$ 。
题解
高情商:在这道题上学了点东西。
低情商:md这么简单的题都不会,我到底是什么玩意。(簡単なことも解らないわ あたしって何だっけ)
这道题的状态有点巧妙,有点 tip。知道直接求恰好的很难,那就设个至少的:设 $f_i$ 表示至少 $i$ 位相同的对数。然后容斥可得到答案。
但问题是怎么求 $f_i$ 。不妨再给要求降低点,让其数对可重复,这样就好求,也好二项式系数容斥。
所以本题由 $f_i$ 的求法确定它的具体意义。
代码
哈希直接 STL,这里的模数是 $2^{64}$ 。
const int N = 1e5 + 5;
inline ll Read() {
ll x = 0, f = 1;
char c = getchar();
while (c != '-' && (c < '0' || c > '9')) c = getchar();
if (c == '-') f = -f, c = getchar();
while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
return x * f;
}
namespace Main {
int n, k;
int a[N][7], C[7][7];
const ull base = 1e9 + 7;
int f[N];
int main () {
for (int i = 0; i <= 6; i++) {
C[i][0] = 1;
for (int j = 1; j <= i; j++) C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
}
n = Read(), k = Read();
for (int i = 1; i <= n; i++)
for (int j = 1; j <= 6; j++)
a[i][j] = Read();
for (int d = 0; d < 64; d++) {
unordered_map <ull, int> m;
int c = __builtin_popcount(d);
for (int i = 1; i <= n; i++) {
ull val = 0;
for (int j = 1; j <= 6; j++) {
if ((d >> j - 1) & 1) val ^= a[i][j];
val *= base;
}
m[val]++;
}
for (auto i: m) f[c] += i.second * (i.second - 1) / 2;
}
f[0] = n * (n - 1) / 2;
for (int i = 6; i >= 0; i--) {
for (int j = i + 1; j <= n; j++) f[i] -= f[j] * C[j][i];
}
printf ("%d\n", f[k]);
return 0;
}
}
int main () {
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
Main::main();
return 0;
}