C. Boboniu and Bit Operations (664 div2 位运算/dp)

C. Boboniu and Bit Operations

题意: 给出两个非负整数的数组a,b,长度分别为n,m。设对于 i , j i,j ij c i = a i c_i =a_i ci=ai& b j b_j bj ,求 c 1 ∣ c 2 ∣ c 3 … … ∣ c n c_1|c_2|c_3……|c_n c1c2c3cn 的最小值。 1 ≤ n , m ≤ 200 1\le n,m\le 200 1n,m200 0 ≤ a i < 2 9 0\le a_i < 2^9 0ai<29 0 ≤ b i < 2 9 0\le b_i < 2^9 0bi<29
思路: 本题有两个切入点。
一、由于 a i 和 b i a_i 和b_i aibi均不超过九位二进制数,所以可以直接从小到大枚举答案ans,当 c i ∣ a n s = = a n s c_i|ans==ans cians==ans 时即为答案。(按位或运算的性质
二、对于表达式的值,直接暴力计算出所有可能的结果,然后取最小的。由于结果可以直接 dp 转移状态。

Code1:

#include
using namespace std;
const int N = 210;

int a[N],b[N];

int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=m;i++) cin>>b[i];
	for(int i=0;i<(1<<10);i++){
		int num=0;
		for(int j=1;j<=n;j++){
			int flag = 0;
			for(int k=1;k<=m;k++){
				if(((a[j]&b[k])|i)==i) flag=1;
			}
			if(flag) num++;
		}
		if(num==n) {
			cout<<i<<"\n";return 0;
		}
	}
}

Code2:

#include
using namespace std;
const int N = 210,M=1<<10;
int a[N],b[N],dp[N][M];

int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=m;i++) cin>>b[i];
	dp[0][0]=1;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			int add = a[i]&b[j];
			for(int k=0;k < M;k++)
			if(dp[i-1][k]) dp[i][k|add]=1;
		}
	}
	for(int i=0;i<M;i++){
		if(dp[n][i]){
			cout <<i;
			return 0;
		}
	}
}

你可能感兴趣的:(CF,DP)