题解 动物园
题目分析
首先,可以求出需要的饲料是哪些,因为每个要求是只要有一个动物的二进制第 (p_j) 位为 (1) ,那么就需要购买第 (q_j) 种饲料,所以可以吧所有动物按位或起来,然后就可以知道要用哪些饲料了。
然后看包含某一二进制位的动物是否可能可以选,如果有 (s) 个二进制位都是可选的,那么动物园就可以饲养一共 (2^s) 种动物,答案就是 (2^s-n) 。
用 vector
或者邻接表来存每一个二进制位需要的饲料是哪些,然后用 bool
或者 bitset
存哪些饲料是要用的,直接扫一遍判断即可。
需要注意的是 (2^{64}) 爆了 unsigned long long
,需要特判。
参考代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ch() getchar()
#define pc(x) putchar(x)
using namespace std;
template<typename T>void read(T&x){
static int f;static char c;
for(c=ch(),f=1;c<'0'||c>'9';c=ch())if(c=='-')f=-f;
for(x=0;c>='0'&&c<='9';c=ch())x=x*10+(c&15);x*=f;
}
template<typename T>void write(T x){
static int q[64];int cnt=0;
if(x==0)return pc('0'),void();
if(x<0)pc('-'),x=-x;
while(x)q[cnt++]=x%10,x/=10;
while(cnt--)pc(q[cnt]+'0');
}
#define ULL unsigned long long
const int maxn=1000005,maxm=1000005,maxk=80,maxc=100000005;
bool vis[maxc];
struct Edge{
int v,nt;
Edge(int v=0,int nt=0):
v(v),nt(nt){}
}e[maxm];
int hd[maxk],num;
void qwq(int u,int v){
e[++num]=Edge(v,hd[u]),hd[u]=num;
}
int main(){
int n,m,c,k;
read(n),read(m),read(c),read(k);
ULL tmp=0;
for(int i=1;i<=n;++i){
ULL a;scanf("%llu",&a);tmp|=a;
}
for(int i=1;i<=m;++i){
int p,q;read(p),read(q);qwq(p,q);
if((tmp>>p)&1)vis[q]=true;
}
int cnt=0;
for(int i=0;i<k;++i){
int ok=true;
for(int j=hd[i];j&&ok;j=e[j].nt){
int v=e[j].v;ok&=vis[v];
}
if(ok)++cnt;
}
if(cnt<64||n>0){
if(cnt==0)printf("%d
",1-n);
else{
ULL ans=1llu<<(cnt-1);
if(ans>=n)ans-=n,ans+=1llu<<(cnt-1);
else ans+=1llu<<(cnt-1),ans-=n;
printf("%llu
",ans);
}
}
else
puts("18446744073709551616");
return 0;
}