題意
度度熊為了完成畢業論文,需要收集一些數據來支撐他的論據,於是設計了一份包含 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 }