题解 动物园

题解 动物园

题目链接

题目分析

首先,可以求出需要的饲料是哪些,因为每个要求是只要有一个动物的二进制第 (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;
}
原文地址:https://www.cnblogs.com/lsq147/p/13944395.html