TopCoder 12792 BitwiseAnd 题解

更好的阅读体验

题意

原题链接

m 个数 {orii},让你添加 nm 个数(设这一共 n 个数为 {ai}),使得:

  1. 1i,jn, aibitandaj0
  2. 1i,j,kn, aibitandajbitandak=0

求字典序最小的 {ai},或者判断无解。

做法

先转成二进制,然后条件就等价于对于每一个二进制位, {ai} 中这一位是 1 的不超过 2。(不满足就无解,我们把 ai 中这一位是 1 记为 这一位在 ai 中出现

那么我们将 a 的前 m 个设为 ori,后面先设为 0

枚举 i,j(1i<jn)(都按从小到大的顺序),然后强制令 aibitandaj0。具体如下:

  • 如果 aibitandaj 已经不为 0,就不考虑下面的了。
  • 如果 imjm,那么无解。(因为都修改不了)
  • 如果 im,那么 ai 修改不了,只有从 aj 下手。如果 ai 中有二进制位只在 ai 出现过一次,那么可以让这一位在 aj 也出现一次。如果有多个这样的二进制位,取最小的。(因为要字典序最小)
  • 否则(i>m,j>m)分两种情况:
    • 如果 ai 有二进制位只在 ai 出现过一次,那么让它在 aj 中出现。多个取最小。(因为要字典序最小)
    • 否则,取以下两种情况中 ai 较小的:
      • 如果有二进制位只在 aj 中出现,那么让它在 ai 中出现。多个取最小。
      • 如果有一个二进制位没有出现过,那么让它在 aibi 中都出现。

看不懂?伪代码版解释:

将只在 ai 处出现一次的最小的 k 记为 occur(ai)(如果没有就是 1)。
将没有出现过的最小的 k 记为 occurmin(如果没有就是 1)。
bitand 是二进制下的按位与,and 是逻辑与(就是 )。

1if aibitandbi02Skip.3elif im and jm4No Solution.5elif im6if occur(ai)=17No Solution.8ajajbitor2occur(ai)9else10if occur(ai)111ajajbitor2occur(ai)12else13id+14if occur(aj)115idmin{id,occur(aj)}16if occurmin117idmin{id,occurmin}18if id=+19No Solution.20aiaibitor2id21ajajbitor2id

证明不难(贪心),当作业

代码

#include <cstdio>
#include <algorithm>
#include <vector>
using std::vector;
typedef long long LL;
const int N = 50 + 5;
int edge[N][N];
int used[70];
vector<int> to[N];
int nw_id() {
	for(int i = 0; i < 60; i++) if(!used[i]) return i;
	return -1;
}
LL ans[N];
class BitwiseAnd {
public:
	vector<LL> lexSmallest(vector<LL> st, int n) {
		int m = st.size();
		for(int i = 1; i <= m; i++) ans[i] = st[i - 1];
		for(int i = 1; i <= m; i++)
			for(int j = 0; j < 60; j++) if(st[i - 1] >> j & 1) {
				if(!used[j]) used[j] = i;
				else if(used[j] != -1) edge[i][used[j]] = edge[used[j]][i] = true, used[j] = -1;
				else return {};
			}
		for(int i = 59; i >= 0; i--) if(used[i] > 0) to[used[i]].push_back(i);
		for(int i = 1; i <= n; i++)
			for(int j = i + 1; j <= n; j++) if(!edge[i][j]) {
				if(i <= m && j <= m) return {};
				else if(i <= m) {
					if(to[i].empty()) return {};
					int id = to[i].back();
					to[i].pop_back();
					ans[j] |= 1LL << id;
					used[id] = -1;
				} else {
					int id;
					if(!to[i].empty()) id = to[i].back(), to[i].pop_back();
					else {
						id = 100;
						if(to[i].empty() && to[j].empty()) id = std::min(id, nw_id());
						if(!to[j].empty()) id = std::min(id, to[j].back()), to[j].pop_back();
					}
					if(id == -1 || id == 100) return {};
					ans[i] |= 1LL << id, ans[j] |= 1LL << id;
					used[id] = -1;
				}
			}
		auto v = vector<LL>(ans + 1, ans + n + 1);
		std::sort(v.begin(), v.end());
		return v;
	}
};
posted @   XxEray  阅读(45)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示