bzoj 1879 容斥

暴力求容斥系数或者直接组合数求容斥系数都可以。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PII pair<int, int>
#define PLI pair<LL, int>
#define ull unsigned long long
using namespace std;

const int N = 55;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000003;

int n, k, m, Pow[N], num[1 << 15], C[N][N];
char s[20][55];
char t[55];

void init() {
    Pow[0] = 1;
    for(int i = 1; i < N; i++) Pow[i] = Pow[i-1] * 26 % mod;
    for(int i = 0; i < N; i++) {
        for(int j = 0; j <= i; j++) {
            if(!j || i == j) C[i][j] = 1;
            else C[i][j] = (C[i-1][j] + C[i-1][j-1]) % mod;
        }
    }
}

int cal(int state) {
    memset(t, '#', sizeof(t));
    for(int j = 0; j < n; j++) {
        if((state>>j)&1) {
            for(int i = 0; i < m; i++) {
                if(s[j][i] != '?') {
                    if(t[i] == '#') t[i] = s[j][i];
                    else if(t[i] != s[j][i]) return 0;
                }
            }
        }
    }
    int cnt = 0;
    for(int i = 0; i < m; i++)
        if(t[i] == '#') cnt++;
    return Pow[cnt];
}

int solve(int k) {
    if(k == -1) return 0;
    int ans = 0;
    for(int s = 1; s < (1<<n); s++) {
        if(s) num[s] = num[s-(s&-s)] + 1;
        if(num[s] > k) {
            int val = cal(s);
            if((num[s] - k)&1) ans = (ans + 1ll*C[num[s]-1][k]*val) % mod;
            else ans = (ans - 1ll*C[num[s]-1][k]*val) % mod;
        }
    }
    return (Pow[m] - ans + mod) % mod;
}

int main() {
    init();
    int T; scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &k);
        for(int i = 0; i < n; i++)
            scanf("%s", s[i]);
        m = strlen(s[0]);
        printf("%d\n", (solve(k) - solve(k-1) + mod) % mod);
    }
    return 0;
}

/*
*/

 

posted @ 2018-10-07 16:42  NotNight  阅读(113)  评论(0编辑  收藏  举报