2018"百度之星"程序设计大赛 - 资格赛 1001 调查问卷 二进制状态压缩

调查问卷

 

 Accepts: 401

 

 Submissions: 1731

 Time Limit: 6500/6000 MS (Java/Others)

 

 Memory Limit: 262144/262144 K (Java/Others)

Problem Description

度度熊为了完成毕业论文,需要收集一些数据来支撑他的论据,于是设计了一份包含 mm 个问题的调查问卷,每个问题只有 'A' 和 'B' 两种选项。

将问卷散发出去之后,度度熊收到了 nn 份互不相同的问卷,在整理结果的时候,他发现可以只保留其中的一部分问题,使得这 nn 份问卷仍然是互不相同的。这里认为两张问卷是不同的,当且仅当存在至少一个被保留的问题在这两份问卷中的回答不同。

现在度度熊想知道,存在多少个问题集合,使得这 nn 份问卷在只保留这个集合的问题之后至少有 kk 对问卷是不同的。

Input

第一行包含一个整数 TT,表示有 TT 组测试数据。

接下来依次描述 TT 组测试数据。对于每组测试数据:

第一行包含三个整数 nn,mm 和 kk,含义同题目描述。

接下来 nn 行,每行包含一个长度为 mm 的只包含 'A' 和 'B' 的字符串,表示这份问卷对每个问题的回答。

保证 1 \leq T \leq 1001≤T≤100,1 \leq n \leq 10^31≤n≤10​3​​,1 \leq m \leq 101≤m≤10,1 \leq k \leq 10^61≤k≤10​6​​,给定的 nn 份问卷互不相同。

Output

对于每组测试数据,输出一行信息 "Case #x: y"(不含引号),其中 x 表示这是第 xx 组测试数据,y 表示满足条件的问题集合的个数,行末不要有多余空格。

Sample Input

Copy

2
2 2 1
AA
BB
2 2 2
AA
BB

Sample Output

Case #1: 3
Case #2: 0

状态压缩

每张问卷填写的结果转换成一个二进制数x,选择哪些题也变成一个二进制数y(选择第i题,则i位为1),则x&y就是调查问卷x在选择的题状态为y的情况下填的问卷, 用一个数组存在选题状态为y下,每种问卷的个数。

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <stack>
#define fora(i,a,b) for(i=a;i<b;i++)
#define fors(i,a,b) for(i=a;i>b;i--)
#define fora2(i,a,b) for(i=a;i<=b;i++)
#define fors2(i,a,b) for(i=a;i>=b;i--)
#define PI acos(-1.0)
#define eps 1e-6
#define INF 0x3f3f3f3f

typedef long long LL;
typedef long long LD;
using namespace std;
const int maxn=1e3+11;
char q[15];
int a[1024][1024];
int main()
{
    int T,t=0,len;
    scanf("%d",&T);
    while(T--)
    {
        int n,m,k;//问卷1e3,问题10,不同1e6
        scanf("%d%d%d",&n,&m,&k);
        int i,j,M=1<<m;
        memset(a,0,sizeof(a));
        fora2(i,1,n)
        {
            scanf("%s",q);
            int tem=0;
            fora(j,0,m)
            {
                tem=tem*2+q[j]-'A';
            }
            fora(j,1,M)
            {
                a[j][tem&j]++;
            }
        }
        int ans=0;
        printf("Case #%d: ",++t);
        if(n*(n-1)/2<k)printf("0\n");
        else
        {
            fora(i,1,M)
            {
                int sum=n*(n-1)/2;
                fora(j,0,M)
                {
                    int tem=a[i][j];
                    sum-=tem*(tem-1)/2;
                }
                if(sum>=k)ans++;
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}

 

posted on 2018-08-04 16:18  一零七  阅读(132)  评论(0编辑  收藏  举报

导航