起床困難綜合症

ZA139發表於2020-10-23

起床困難綜合症

題意

給你N個門,每個門的操作為AND,XOR,OR中的一種,每個門有一個運算元,現在讓一個[0,m]的數字x依次通過這n扇門,問最大的結果是多少

思路

位運算沒有進位,所以可以每一位單獨運算

所以我們讓在[0,m]範圍的每一位去通過這n道門,檢視結果即可

因為x有[0,m]範圍的限制,所以我們要儘可能的讓x最小

即對於x的第i位當且僅當

x的第i位為0時通過n道門得到的結果不為1

且x的第i位為1時通過n道門得到的結果為1時

x的第i位才為1,否則都是0

最後獲得x跑一邊n道門就是答案啦

程式碼

#include<cstdio>
#include<utility>
#include<iostream>
#include<string>
using namespace std;
long long n, m;
pair<string, long long>gates[100005];
long long pow(long long a, long long b) {
	long long ans = 1;
	long long base = a;
	while (b > 0) {
		if (b & 1) {
			ans *= base;
		}
		base *= base;
		b >>= 1;
	}
	return ans;
}
bool fun(long long k) {
	bool ans = 0;
	for (long long i = 0; i < n; i++) {
		long long nu = gates[i].second >> k & 1;
		if (gates[i].first == "AND") {
			ans &= nu;
		}
		else if (gates[i].first == "OR") {
			ans |= nu;
		}
		else {
			ans ^= nu;
		}
	}
	if (ans) {
		return false;
	}
	else {
		ans = 1;
		for (long long i = 0; i < n; i++) {
			long long nu = gates[i].second >> k & 1;
			if (gates[i].first == "AND") {
				ans &= nu;
			}
			else if (gates[i].first == "OR") {
				ans |= nu;
			}
			else {
				ans ^= nu;
			}
		}
		if (ans) {
			return true;
		}
		else {
			return false;
		}
	}
}
string s;
long long t1;
int main(void) {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	long long temp = 1;
	for (long long i = 0; i < n; i++) {
		cin >> s >> t1;
		gates[i] = make_pair(s, t1);
	}
	long long ans = 0;
	long long x = 0;
    //獲取位的上限
	for (long long i = 0; i < 999; i++) {
		if ((1 << i) == m) {
			x = i;
			break;
		}
		else if ((1 << i) > m) {
			x = i-1;
			break;
		}
	}
	long long base = pow(2, x);
    //優先使高位開始貪心
	for (long long i = x; i >= 0; i--) {
		if (fun(i)) {
			ans += base;
		}
		if (ans > m) {
			ans -= base;
			break;
		}
		base /= 2;
	}
    //得到的ans跑一邊n道門
	for (long long i = 0; i < n; i++) {
		long long nu = gates[i].second;
		if (gates[i].first == "AND") {
			ans &= nu;
		}
		else if (gates[i].first == "OR") {
			ans |= nu;
		}
		else {
			ans ^= nu;
		}
	}
	printf("%lld\n", ans);
	return 0;
}

相關文章