分析 :
那个表达式其实就是对异或之后的值取反
得到的一个字符串,位置为1则有对应的值
所以预处理出所有的结果串
然后算出各种串的数量
再预处理出每种串和其他种串得到的结果
做一个前缀和即可
不要用cin 会被卡掉 wa了好几发 /(ㄒoㄒ)/~~
代码 :
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
int n , m , q ;
int a[7891] ;
int v[15] ;
int mp[7894][123] ;
int get_num(char s[]){ //求字符串对应的十进制数
int tmp = 0 ;
for(int j = n - 1 ; j >= 0 ; j--){
if(s[j] == '1') tmp |= (1 << (n - 1 - j)) ;
}
return tmp ;
}
void solve(){ //预处理
for(int i = 0 ; i < 1 << n ; i++){
for(int j = 0 ; j < 1 << n ; j++){
if(!a[j]) continue ; //没有对应的数 直接跳过
int sum = 0 ;
for(int k = 0 ; k < n ; k++){
if((i & (1 << k)) == (j & (1 << k))) sum += v[n-k] ;
}
if(sum > 100) continue ; //题目k范围是小于100 , 所以大于100的不要
mp[i][sum] += a[j] ;
}
}
}
int main(){
ios::sync_with_stdio(false) ;
cin.tie(0) ;
cout.tie(0) ;
scanf("%d%d%d" , &n , &m , &q) ;
for(int i = 1 ; i <= n ; i++)
scanf("%d" , &v[i]) ;
for(int i = 1 ; i <= m ; i++){
char s[15] ;
int tmp = 0 ;
scanf("%s" , s) ;
tmp = get_num(s) ;
a[tmp]++ ;
}
solve() ;
for(int i = 0 ; i < 1 << n ; i++){ //求前缀和
for(int j = 1 ; j <= 100 ; j++)
mp[i][j] += mp[i][j-1] ;
}
while(q--){
char s[15] ;
int w ;
scanf("%s%d" , s , &w) ;
int tmp = get_num(s) ;
printf("%d\n" , mp[tmp][w]) ;
}
return 0 ;
}