#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; /* 1. 利用二进制枚举子集(问题的组合 <= 2 ^ m - 1),二进制的位为1,表示选择了它 2. 对 1 的整数进行二进制解码,即得到选择了哪几个问题 3. 计算每一份调查问卷的hash值(A为1,B为0),利用mark[val]数组记录hash值为val的有多少个调查问卷 4. 计算有多少对问卷不同 hash1->a1;hash2->a2;...hashk->ak; 不同对数 = a1(a2+a3+...+ak) + a2(a3+a4+...+ak) + ... + ak-1(ak) */ int mark[2000]; char str[1050][15]; int pow2[15]; vector<int> que; int T; int n,m,k; int ans; void deCode(int s) { int tmp = s; int index = 1; while (tmp != 0) { if (tmp % 2 == 1) { que.push_back(index); } index++; tmp = tmp / 2; } return; } int main() { scanf("%d",&T); int t = 1; //初始化2 ^ 1,2 ^ 2...... memset(pow2,0,sizeof(pow2)); pow2[0] = 1; for (int i = 1;i < 15;i++) { pow2[i] = pow2[i-1] * 2; } // while (t <= T) { scanf("%d%d%d",&n,&m,&k); for (int i = 0;i < n;i++) { scanf("%s",str[i]); } ans = 0; //枚举 int maxS = pow2[m] - 1; int hash = 0; for (int i = 1;i <= maxS;i++) { que.clear(); deCode(i); memset(mark,0,sizeof(mark)); //计算每个string的hash值 for (int p = 0;p < n;p++) { hash = 0; for (int q = 0;q < que.size();q++) { if (str[p][que[q] - 1] == 'A') { hash += pow2[que[q] - 1]; } } mark[hash]++; } //从后往前遍历,用sumSuffix记录aj+aj+1+...+ak; int sum = 0; int sumSuffix = 0; for (int p = maxS;p >= 0;p--) { if (mark[p] != 0) { sum += mark[p] * sumSuffix; sumSuffix += mark[p]; } } if (sum >= k) { ans++; } } printf("Case #%d: %d\n",t++,ans); } return 0; }