D. The Wu
http://codeforces.com/contest/1017/problem/D
题意:给你有n个字符的01串,串中每个位置都有一个价值,同事给你有m个字符串的集合,集合中的串有n个字符,也都是01串,给你q个询问,每行有一个01串,还有一个整数k,将这个串和集合中的串进行比较,如果两个串中某一个位置的字符相同,那么就加上这一位的价值,问你在集合s中有多少个串与这个串比较之后得到的和小于k,输出满足条件的串的数量。
思路:
我们可以发现n很小,k也很小,我们可以把字符串转化为整数,通过(2^n)*(2^n)*n的时间复杂度预处理所有01串排列满足条件的数量。
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <map>
#include <set>
#include <cstring>
#include <cmath>
using namespace std;
int a[20];
int num[1<<13][150];
char s[20];
int numm[1<<13];
int main()
{
int n,q,m;
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 val=0;
for(int j=0; j<n; j++)
{
val=val*2+s[j]-'0';
}
numm[val]++;
}
for(int i=0; i<(1<<n); i++)
{
for(int j=0; j<(1<<n); j++)
{
int val=0;
for(int k=0; k<n; k++)
{
if(((i^j)&(1<<k))==0)
{
val+=a[n-k-1];
}
}
if(val<=100)
{
num[i][val]+=numm[j];
}
}
}
while(q--)
{
int ans=0;
int k;
scanf("%s%d",s,&k);
int x=0;
for(int i=0; i<n; i++)
{
x=x*2+s[i]-'0';
}
for(int i=0; i<=k; i++)
{
ans+=num[x][i];
}
printf("%d\n",ans);
}
return 0;
}