题面
题目描述(就挺抽象的)
精灵一族信任与她的善良、勇敢与坚韧,
为了拯救这即将凋零的世界,
(鬼知道FMT是什么玩意) 融会贯通,以更好地对付黑暗,并没有时间来考虑这个问题。如果你能告诉她答案,这个可爱又善良的女孩子会对你感激不尽。
输入描述
为了便于输入输出,约定用一个十进制整数来表示魔力晶板的状态。这个整数的二进制下第 i 位为 1 ,则表示魔力晶板的第 i+1 个位置有魔力水晶,反之则没有。
第一行一个正整数 T ,表示数据组数。
对于每组数据,第一行两个正整数 n,m ,意义如问题描述中所述。
接下来 n 行,每行一个整数 x 表示 feluamn 拥有的魔力晶板的状态。
接下来一行一个非负整数 c ,意义如问题描述中所述。
接下来一行 c 个正整数,第 i 个正整数表示 bi 。
接下来一行一个正整数 q ,表示询问数量。接下来 q 行,每行一个非负整数表示 feluamn 所需的魔力晶板的状态。
输出描述
对于每组数据,输出 q 行。第 i 行一个非负整数表示第 i 个询问的答案。注意不同的数据之间不需要用空行隔开。
样例数据
见此
数据范围
对于所有数据,T≤5,1≤q,n≤100000,1≤m≤20,1≤bi≤m,c<m 。保证代表魔力晶板状态的整数不超过 m 位。相同的 bi 只算一个。
对于20% 的数据:1≤q,n≤1000
对于另外20% 的数据:1≤m≤7
对于另外30% 的数据:c=0
对于另外40% 的数据:没有特殊限制
题解
首先,我们可以发现
$ans | =(1«b_{i})$ |
其中
但是显然,不只有
判断不可行的方式是:如果
注意,
那么如何判断是否合法?
首先,我们要明确不合法的情况。当那个位置上没有魔力水晶时,你还进行去掉的操作,那就是不合法的。
由于
ans&x==ans
时合法,否则不合法。
接下来就简单了,令
最后对于每个询问
代码中,用
好了,请食用下面这份代码:
#include<bits/stdc++.h>
using namespace std;
inline int read()//快读函数,可以快速读取(输入)
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
return s*w;
}
const int N=25;
const int NN=1e6+114514;
int f[NN],t[N];
int main()
{
int T;
T=read();
while(T--)
{
int tlen=1;
memset(f,0,sizeof(f));
int m,n,q,c,maxn=0,ans=1;
n=read();
m=read();
for(int i=1;i<=n;i++)
{
int x;
x=read();
f[x]++;
maxn=max(maxn,x);
}
c=read();
for(int i=1;i<=c;i++)
{
int k;
k=read();
ans|=(1<<k);
}
t[1]=ans;
while(t[tlen]<=maxn)
{
for(int i=maxn;i>=t[tlen];i--)
{
if((i&t[tlen])==t[tlen]) f[i-t[tlen]]+=f[i];
}
t[tlen+1]=(t[tlen]<<1);
tlen++;
}
q=read();
for(int i=1;i<=q;i++)
{
int qus;
qus=read();
printf("%d\n",f[qus]);
}
}
}
这道题的出题者实在是天才。
还有人说高维前缀和、