由于只有4位,我们可以考虑直接 24 枚举所有钦定要选的集合并容斥掉。 感觉并不需要二项式反演。
自己写的代码只有 60分, 求大家帮忙看看/bx
#include <bits/stdc++.h>
using namespace std;
const int N = 5e4 + 10;
using i64 = long long;
namespace IO {
template <typename T>
inline void read(T &x) {
x = 0; int r = 1;
char ch = getchar();
while (!isdigit(ch)) r = ch == '-' ? -1 : 1, ch = getchar();
while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
x *= r;
}
template <typename T>
inline void write(T x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
}
using namespace IO;
int n, d;
i64 ans;
char s[N][10];
vector<char> v;
map<vector<char>, int> mp;
void solve(int x) {
int cnt = __builtin_popcount(x);
if(cnt < d) return;
i64 ret = 0;
mp.clear();
for (int i = 1; i <= n; ++ i) {
v.clear();
for (int j = 1; j <= 4; ++ j) {
if (x & (1 << (j - 1)))
v.push_back(s[i][j]);
}
mp[v] ++;
}
for (auto it = mp.begin(); it != mp.end(); it ++) {
ret += 1ll * (it -> second) * (it -> second - 1) / 2;
}
ans += (cnt & 1) ? -ret : ret;
}
signed main() {
// freopen("test.in", "r", stdin);
read(n), read(d);
d = 4 - d;
for (int i = 1; i <= n; ++ i) scanf("%s", s[i] + 1);
for (int i = 0; i < 16; ++ i) solve(i);
write(ans), putchar('\n');
}