先看数据规模
20%的数据点pi互不相同,那么答案就是2^(k-m)-n。这个20分是非常容易拿的。
当然,本题是要拿满分的。拿满分,关键是看两个点
一是位运算(怎么想到的?看数据规模,肯定要注意时间复杂度了),将动物编号 | 后得到一个二进制数an,接下来将an与食物清单&,如果得到的非零,那么这个食物可选可不选,如果是零,那么这个食物就不能选。将这些不能选的位置数量记下来,记作cns。那么答案就是2^(k-cns)-n。
二是数据范围,因为k最大可取64,而2^64超出了ull的上限,可以特判,当k-cns==64,且n=0的时候,直接输出2^64。可以用window计算器科学计数器模式计算得到。
本题致命点在1<<p,没有说明,则它的最高位是符号位,因此要改成1ull <<p
#include<bits/stdc++.h>
#define maxn 100000005
#define ll long long
#define ull unsigned long long
using namespace std;
unsigned long long n,m,c,k;
unsigned long long a,an=0,p,q,cns;
bool vis[maxn];
int main()
{
freopen("zoo14.in","r",stdin);
cin>>n>>m>>c>>k;
for(int i=1;i<=n;i++)
{
cin>>a;
an|=a;
}
//cout<<an<<endl;
for(int i=1;i<=m;i++)
{
cin>>p>>q;
if(an & (1ull<<p)) continue;//第p个食物需要购买,不影响答案——————这里要写成1ull<<p,不能写1<<p,否则对于第14个测试点cns=10
vis[p]=1;//第p个食物不用购买,将影响答案
}
for(int i=0;i<k;i++) //统计有多少种食物限制没有用到,这些限制不要启用
if(vis[i])cns++;
if(k-cns==64)
{
if(n==0)
printf("18446744073709551616\n"); //用电脑自带的计算器科学计数器模式计算得到2^64
else
cout<<(unsigned long long)(-n) << endl;
return 0;
}
cout<<(unsigned long long)pow(2,k-cns)-n;
return 0;
}