题目:
分析
每个格子储存的都是二的多少次方,所以可以考虑使用二进制表示,
1 | 1 |
---|---|
2 | 10 |
4 | 100 |
8 | 1000 |
四个二进制数,一共有1,10,11,100,101,111,110,1000,1001,1010,1110,1111……
不难发现规律,实际上就是长度为4的二进制数的排列组合。
缺失了k个,同样转化为二进制,比如,若缺失第三个格子4,则就是从右往左第三位必是0,缺少了2 *2 *2=8种情况。
所以几个重要的数据是:
1.格子总数->确定二进制的长度
2.缺失了哪几个格子->确定二进制数中那几位是为0
3.所需要的取到的二进制数->与给出的二进制进行比对
示例
以示例二为例:
7 2 35
2 3
7->1000000 (七位) 35->100011
2->10 3->100 表明从右往左的第二第三位必为0
然而不难发现35的二进制位从右往左的第二位却是1,所以输出NO
拓展
&运算通常用于二进制取位操作。
例如一个数 &1的结果就是取二进制的最末位。 这可以用来判断一个整数的奇偶,二进制的最末位为0表示该数是偶数,最末位为1表示该数为奇数
例如a&(a-1)=?的含义:去掉a最右边的1
a>>b表示二进制右移b位(去掉末b位),相当于a除以2的b次方(取整)。
想办法用>>代替除法运算可以使程序的效率大大提高!
AC代码
#include<iostream>
using namespace std;
int main(){
long long n,k,s;
cin>>n>>k>>s;
while(k--){
long long temp;
cin>>temp;
if(s>>(temp-1)&1)
return puts("NO"),0;
}
cout<<"YES";
return 0;
}