求助 !不太明白直接容斥做法的错误性
查看原帖
求助 !不太明白直接容斥做法的错误性
168223
ShuKuang楼主2021/12/22 19:57

由于只有4位,我们可以考虑直接 242^4 枚举所有钦定要选的集合并容斥掉。 感觉并不需要二项式反演。

自己写的代码只有 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');
}
2021/12/22 19:57
加载中...