题意:给你n m q,表示在这一组数据中所有的01串长度均为n,然后给你一个含有m个元素的multiset,之后有q次询问。每次询问会给你一个01串t和一个给定常数k,让你输出串t和multiset里面多少个元素的“Wu”值不超过k。对于“Wu”值的定义:如果两个01串s和t在位置i上满足s[i]==t[i],那么加上w[i],处理完s和t的所有n位之后的结果即为这两个01串的“Wu”值。
样例解释:第1行为n,m,q;第2行为w[1]...w[n],表示01串第i位的权值为w[i];之后m行为multiset里的m个01串;之后q行为q次询问。以样例1中的第一次询问为例:t=00,k=20。与multiset中的每个元素比较(假设第i个元素为m[i]):
m[1]:01,与00相同的是第一位,所以权值s=w[1]=40;
m[2]:01,与00相同的是第一位,所以权值s=w[1]=40;
m[3]:10,与00相同的是第二位,所以权值s=w[2]=20;
m[4]:11,没有某一位与00相同,所以权值s=0;
而上述四种比较结果中s<=20的是后两种,所以输出2。之后的询问以此类推。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
int n,m,q;
int w[15];
int cnt[5005];
char tp[15];
struct node
{
int val,num;
friend bool operator<(node a,node b)
{
if(a.val==b.val)
return a.num<b.num;
else
return a.val<b.val;
}
}itm[5005];
bool cmp(node a,node b)
{
return a.val<b.val;
}
int ansn[4105][4105];
int main() {
while(~scanf("%d%d%d",&n,&m,&q))
{
memset(cnt,0,sizeof(cnt));
for(int i=0;i<n;i++)
{
scanf("%d",&w[i]);
}
while(m--)
{
scanf("%s",tp);
int cur=0;
for(int i=0;i<n;i++)
{
cur+=(1<<i)*(tp[i]-'0');
}
cnt[cur]++;
}
int len=(1<<n);
for(int i=0;i<len;i++)
{
int val=0;
for(int j=0;j<n;j++)
{
if(((i>>j)&1)!=0)
{
val+=w[j];
}
}
itm[i].val=val;itm[i].num=i;
}
sort(itm,itm+len);
for(int i=0;i<len;i++)
{
for(int j=0;j<len;j++)
{
int cur=i^itm[j].num;
cur=cur^(len-1);
ansn[i][j]=cnt[cur];
if(j>0)
ansn[i][j]+=ansn[i][j-1];
}
}
while(q--)
{
int k;
scanf("%s",tp);
scanf("%d",&k);
int cur=0;
for(int i=0;i<n;i++)
{
cur+=(1<<i)*(tp[i]-'0');
}
node nxt;nxt.val=k;nxt.num=1e9+7;
int id=upper_bound(itm,itm+len,nxt)-itm;
if(id==0)
printf("0\n");
else
{
printf("%d\n",ansn[cur][id-1]);
}
}
}
return 0;
}