题 意:给你m个长度为n个01串t,q个长度为n的查询串s,如果ti = si 则他们的价值为wi,否则为0,pair< t ,s >的总价值为各个字符的价值之和。
数据范围:
1<=n<=12
1<=q,m<=5e5
0<=wi<=100
输入样例:
2 4 5
40 20
01
01
10
11
00 20
00 40
11 20
11 40
11 60
输出样例:
2
4
2
3
4
思 路:先把每一个01串转化成对应的数字,预处理所有可能询问的串和已经有的串。
收 获:又多学习了一种字符串的解题姿势,见识了二维前缀和。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 12;
int sum[1<<maxn+1][105];
int a[maxn+1];
int cnt[1<<maxn+1];
char s[maxn+1];
int n,m,q,k;
int main(){
scanf("%d %d %d",&n,&m,&q);
for(int i=0;i<n;i++)scanf("%d",&a[i]);
for(int i=0;i<m;i++){
scanf("%s",s);
int tmp = 0;
for(int j=0;j<n;j++){
tmp |= ((s[j]-'0')<<j);
}
cnt[tmp]++;
}
for(int i=0;i<(1<<n);i++){
for(int j=0;j<(1<<n);j++){
int tmp = 0;
for(int k=0;k<n;k++){
if((i&(1<<k)) ==(j&(1<<k))) tmp+=a[k];
}
if(tmp > 100) continue;
sum[i][tmp] += cnt[j];
}
}
for(int i=0;i<(1<<n);i++){
for(int j=1;j<=100;j++){
sum[i][j] += sum[i][j-1];
}
}
for(int i=0;i<q;i++){
scanf("%s%d",s,&k);
int tmp = 0;
for(int j=0;j<n;j++){
tmp|=((s[j]-'0')<<j);
}
printf("%d\n",sum[tmp][k]);
}
return 0;
}