【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\n",ans); 39 } 40 return 0; 41 }