这道题状压预处理很妙把s集合中出现的每个字符串都求出他的状压值,之后再判断任何一个范围内的数字如果和s内作用后wu值等于x,那么对应s中几个字符串
预处理后就可以查询了
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int w[15],cnt[4100],sum[4100][105]; void solve(){ int n,m,q;scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=n;i++) scanf("%d",&w[i]); for(int i=1;i<=m;i++){ char s[15];scanf("%s",s); int x=0; for(int j=0;j<n;j++) if(s[j]=='1') x+=1<<(n-j-1); cnt[x]++; } for(int i=0;i<(1<<n);i++){ for(int j=0;j<(1<<n);j++){ if(!cnt[j]) continue; int x=0; for(int k=0;k<n;k++){ if((i&(1<<k))==(j&(1<<k))) x+=w[n-k]; if(x>100) break; } if(x<=100) sum[i][x]+=cnt[j]; } } while(q--){ char s[15];int k;scanf("%s%d",s,&k); int x=0;for(int i=0;i<n;i++) if(s[i]=='1') x+=1<<(n-i-1); int ans=0;for(int i=0;i<=k;i++) ans+=sum[x][i]; printf("%d ",ans); } } int main(){ solve(); return 0; }