Problem - D - Codeforces
Childan正在编造一个传奇故事并试图出售他的伪造品——一条带有强烈“Wu”感的项链给Kasoura家族。但是,Kasoura先生正在质疑Childan故事的真实性。因此,他将询问有关Childan所谓的“个人珍藏”项链的一些问题。
这个“个人珍藏”是一个由m个“01-字符串”组成的多重集合S。
“01-字符串”是包含n个字符“0”和“1”的字符串。例如,如果n=4,则字符串“0110”、“0000”和“1110”都是“01-字符串”,但“00110”(有5个字符而不是4个)和“zero”(不允许的字符)则不是。
注意,多重集合S可以包含相同的元素。
经常,Kasoura先生会提供一个“01-string”t,并询问Childan有多少个字符串s在多重集合S中,使得对于对(s,t),其“Wu值”不大于k。
Mrs. Kasoura和Mr. Kasoura认为,如果si = ti(1≤i≤n),则字符对的“Wu值”等于wi,否则为0。字符对的“Wu值”是每个字符对的“Wu值”的总和。请注意,每个“01-字符串”的长度都是相等的n。
例如,如果w=[4,5,3,6],“Wu”(“1001”,“1100”)为7,因为这些字符串仅在第一和第三位置上具有相等的字符,因此w1 + w3 = 4 + 3 = 7。
您需要帮助Childan回答Kasoura先生的查询。也就是找到多重集合S中的字符串数量,使得对于对的“Wu值”不大于k。
输入
第一行包含三个整数n、m、q(1≤n≤12,1≤q,m≤5×105)-“01-strings”的长度,多重集合S的大小和查询数量。
第二行包含n个整数w1、w2、…、wn(0≤wi≤100)-第i个字符的值。
每个接下来的m行包含长度为n的“01-string”s - 多重集合S中的字符串。
每个接下来的q行包含长度为n和整数k(0≤k≤100)的“01-string”t - 查询。
Examples
Input
Copy
2 4 5 40 20 01 01 10 11 00 20 00 40 11 20 11 40 11 60
Output
Copy
2 4 2 3 4
Input
Copy
1 2 4 100 0 1 0 0 0 100 1 0 1 100
Output
Copy
1 2 1 2
题解:
串的数量和询问的次数都很多,说明答案应该会被预处理,但是这么大的数据该怎么预处理
我们可以观察到n的范围只有12,并且每个位置只会有01
我们枚举所有串2^12 * 2^12
再加上比较的过程*12,时间复杂度大概在1e8,而评测机一般1s可以跑1e8次,题目给我们限制的是2s,
所以刚好可以过
#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
#define int long long
typedef pair<int,int> PII;
typedef unsigned long long ULL;
const int N = 3e5 + 10;
int mod = 1e9 + 7;
int cnt[N];
int w[N];
int sum[80004][104];
void solve()
{
int n,m,q;
cin >> n >> m >> q;
for(int i = 1;i <= n;i++)
{
cin >> w[n - i];
}
for(int i = 1;i <= m;i++)
{
string s;
cin >> s;
int res = 0;
for(int j = 0;j < s.size();j++)
{
res = res*2;
if(s[j] == '1')
{
res++;
}
}
cnt[res]++;
}
for(int i = 0;i < (1 << n);i++)
{
for(int j = 0;j < (1 << n);j++)
{
int res = 0;
for(int k = 0;k < n;k++)
{
if((i&(1 << k)) == (j&(1 << k)))
{
res += w[k];
}
}
if(res <= 100)
sum[i][res] += cnt[j];
}
for(int j = 1;j <= 100;j++)
sum[i][j] += sum[i][j - 1];
}
while(q--)
{
string s;
int x;
cin >> s >> x;
int res = 0;
for(int j = 0;j < s.size();j++)
{
res = res*2;
if(s[j] == '1')
{
res++;
}
}
cout << sum[res][x] <<"\n";
}
}
signed main()
{
ios::sync_with_stdio(0 );
cin.tie(0);cout.tie(0);
int t = 1;
// cin >> t;
while(t--)
{
solve();
}
}