因为每个询问的k足够小(小于100),考虑将k变为答案的一维,然后可行状态最多有2^12个,所以最终答案的数组可以开成【4096】【100】。因为是小于等于k的个数,所以用前缀和求解比较方便。预处理数组p【4096】【4096】代表ij状态的Wu值,pre【i】【j】代表i状态k=j时s集合中与j状态的Wu值小于等于k的串的数量
太弱了自己
#include<bits/stdc++.h>
#define mod 1000000007
#define For(i,m,n) for(int i=m;i<=n;i++)
#define Dor(i,m,n) for(int i=m;i>=n;i--)
#define LL long long
#define lan(a,b) memset(a,b,sizeof(a))
using namespace std;
int to[4100];
int p[4100][4100];
int pre[4100][110];
int w[110];
map<int ,int> run;
int powi[20]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096};
int main()
{
int n,q,m;
while(~scanf("%d%d%d",&n,&m,&q))
{
run.clear();
lan(w,0);
lan(to,0);
lan(p,0);
lan(pre,0);
Dor(i,n-1,0)
scanf("%d",&w[i]);
for(int i=0;i<=powi[n]-1;i++)
{
int k=i;
for(int j=11;j>=0;j--)
{
if(k>=powi[j])
to[i]+=w[j],k-=powi[j];
}
}
for(int i=0;i<=powi[n]-1;i++)
for(int j=0;j<=powi[n]-1;j++)
{
int tem=i^j^(powi[n]-1);
p[i][j]=to[tem];
}
For(i,1,m)
{
char s[20];
scanf("%s",s);
int sum=0;
For(i,0,n-1)
if(s[i]=='1')
sum+=powi[n-i-1];
run[sum]++;
}
for(int i=0;i<=powi[n]-1;i++)
for(int j=0;j<=powi[n]-1;j++)
{
if(p[i][j]>100)continue;
pre[j][p[i][j]]+=run[i];
}
for(int i=0;i<=powi[n]-1;i++)
for(int j=0;j<=100;j++)
pre[i][j]+=pre[i][j-1];
For(i,1,q)
{
char s[20];
int k;
scanf("%s",s);
int sum=0;
For(i,0,n-1)
if(s[i]=='1')
sum+=powi[n-i-1];
scanf("%d",&k);
printf("%d\n",pre[sum][k]);
}
}
return 0;
}