【2018百度之星资格赛】1001 调查问卷

题意

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

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

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

分析

本来听说资格赛做一个题就行,过了签到后就去睡觉了,醒了后听说这比赛的评测鸡跑的贼快,就瞎搞了一发a,然后··就过了?????

思路就是··用状态压缩瞎搞一下。

f[i][S]表示前i个问卷,问题集合是二进制表示的S,有多少对不同的问卷。

f[i][S]=f[i-1][S]+i-(前i里有多少和第i个问卷S问题相同的问卷数目)

就酱

下面是代码

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 
 6 using namespace std;
 7 const int maxn=1000+100;
 8 
 9 int T,n,m,k;
10 char s[maxn][15];
11 int f[maxn][1<<11];
12 int vis[maxn];
13 int main(){
14     scanf("%d",&T);
15     for(int t=1;t<=T;t++){
16         printf("Case #%d: ",t);
17         scanf("%d%d%d",&n,&m,&k);
18         for(int i=1;i<=n;i++)
19             scanf("%s",s[i]);
20         for(int ss=0;ss<(1<<m);ss++){
21             memset(vis,0,sizeof(vis));
22             for(int i=1;i<=n;i++){
23                 int S=0;
24                 for(int j=0;j<m;j++){
25                     if(ss&(1<<j)&&s[i][j]=='A'){
26                         S|=(1<<j);
27                     }
28                 }
29                 vis[S]++;
30                 f[i][ss]=f[i-1][ss]+i-vis[S];
31             }
32         }
33         int ans=0;
34         for(int i=0;i<(1<<m);i++){
35             if(f[n][i]>=k)
36                 ans++;
37         }
38         printf("%d
",ans);
39     }   
40 return 0;
41 }
View Code
原文地址:https://www.cnblogs.com/LQLlulu/p/9419232.html