2019哈尔滨理工大学校赛B题 状态压缩dp
题目描述:
非常有意思的题,比赛中是队友过的,题目意思是如上。
解题思路
把所有存在a[i]使其&为0的值标记,再依次判断a[i]是否被标记,实现如下:初始化把所有a[i]^11111…111(二进制)的值k标记为1,即k&a[i]必为0。此时二进制下的k存在a[i]使其&为0,则我们可以在k的基础上,一步步把他二进制中的1一个一个去掉的值标记,去掉后的值也肯定存在a[i]使其&为0。详情看代码:
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
using namespace std;
typedef long long ll;
const ll maxn=(1<<20)-1;
ll a[maxn+5],dp[maxn+5];
int main(){
ll n;
while(scanf("%lld",&n)==1){
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
dp[maxn^a[i]]=1;
}
for(int i=maxn;i>=1;i--){
if(dp[i]){//每个数只减一个1,减完后的数下次遍历到会继续减
for(int j=0;j<=20;j++){
if(i&(1<<j)){
dp[i^(1<<j)]=1;
}
}
}
}
for(int i=1;i<=n;i++){
if(dp[a[i]]) printf("YES\n");
else printf("NO\n");
}
}
}
来源:CSDN
作者:HRBU_Bigspot
链接:https://blog.csdn.net/weixin_43562213/article/details/103450103