D. The Wu
#include<stdio.h>
#include<vector>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<fstream>
#include<math.h>
#include<stack>
#include<bitset>
#include<utility>
using namespace std;
typedef long long ll;
const double eps=0.0000000000001;
int n,m,q;
int cm;
int w[15];
char s[5000][15];//存储不重复的s(最长12位,转换为十进制最长且最大序列值为4096)
int sum[5000][105];//n长度的每个可能的序列所求值<=k的个数
int cn[5000];//m太大,会超时,存相同的s个数
int mypow(int a){
//计算2的a次方
int ans=1;
for(int i=1;i<=a;i++){
ans*=2;
}
return ans;
}
int cg(char*c){
//二进制转十进制
int a=c[0]-'0';
for(int i=1;i<n;i++){
a*=2;
a+=(c[i]-'0');
}
return a;
}
void bg(int it,char*c){
//十进制转二进制
int i=n-1;
while(i>=0){
if(it==0){
c[i]='0';
}
else c[i]=it%2+'0';
it/=2;
i--;
}
}
void cal(int k){
char t[12]={'0'};
bg(k,t);
for(int j=0;j<cm;j++){
int p=0;
for(int l=0;l<n;l++){
if(s[j][l]==t[l]){
p+=w[l];
}
}
if(p<=100)sum[k][p]+=cn[cg(s[j])];
//!!!虽然k<=100,实际算出来的数会超过(第20个测试点)
}
}
void init(){
//预处理
memset(sum,0,sizeof(sum));
int k=0;
for(;k<=mypow(n)-1;k++){
cal(k);
}
for(int i=0;i<=k+1;i++){
for(int j=1;j<=100;j++){
sum[i][j]+=sum[i][j-1];
}
}
}
int main(){
while(~scanf("%d%d%d",&n,&m,&q)){
for(int i=0;i<n;i++){
scanf("%d",&w[i]);
}
memset(cn,0,sizeof(cn));
cm=0;
for(int i=0;i<m;i++){
scanf("%s",&s[cm]);
if(cn[cg(s[cm])]==0){
cn[cg(s[cm])]++;
cm++;
}
else cn[cg(s[cm])]++;
}
init();
char t[15];
int k;
for(int l=0;l<q;l++){
scanf("%s",&t);
scanf("%d",&k);
printf("%d\n",sum[cg(t)][k]);
}
}
return 0;
}
感觉二进制和十进制转换和预处理还是用了很多时间,其他大大运行时间少很多,但是骚操作無理啊