比赛链接:
https://codeforces.com/contest/1634
B. Fortune Telling
题目大意:
\(Alice\) 和 \(Bob\) 玩游戏,\(Alice\) 有一个数 \(x\),\(Bob\) 有一个数 \(x + 3\),现有 \(n\) 个数字 \(a_1,a_2,...,a_n\),它们可以用自己的数从 1 开始一直到 \(n\),和 \(a_i\) 进行异或运算或者加法运算,某个人如果可以用自己的数得到 \(y\),那么这个人就赢了,现在知道他们俩中一定有个人获胜,问是谁。
思路:
可以知道加法和异或运算对数的奇偶性的改变是一致的,举个例子,对于加法运算来说,1 + 1 = 2,1 + 0 = 1,0 + 1 = 1,0 + 0 = 0,对于异或运算 1 ^ 1 = 0,1 ^ 0 = 1,0 ^ 1 = 1,0 ^ 0 = 0。
再加上两个人初始的数奇偶性不同,又有一个人一定会获胜,所以我们只需要 \(x\) 先和序列 \(a\) 中的所有数进行加法或者异或运算,得出来的数和 \(y\) 进行奇偶性比较,如果一样,那么 \(Alice\) 获胜,反之,\(Bob\) 获胜。
代码:
#include <bits/stdc++.h>
using namespace std;
#define LL long long
LL T, n, x, y, a;
void solve(){
scanf("%lld%lld%lld", &n, &x, &y);
for (int i = 0; i < n; ++ i)
scanf("%lld", &a), x ^= a;
if ((x + y) % 2 == 0) cout << "Alice\n";
else cout << "Bob\n";
}
int main(){
cin >> T;
while (T--)
solve();
return 0;
}
D. Finding Zero
题目大意:
给定一个未知序列,其中一个元素为 0。最多进行 \(2n - 2\) 次询问,每次询问的格式为 "? i j k",会返回 \(max(i, j, k) - min(i, j, k)\) 的值,要求通过询问去找到序列中 0 的位置。
最后可以猜两个位置,输出 "! x y",若 \(a_x = 0\) 或 \(a_y = 0\),则获胜。
思路:
官方题解的思路。
只需要找到两个可能为 0 的位置就可以。
对于 4 个元素 \(a, b, c, d\),假设 a = 0,b <= c <= d。定义 \(\overline a = max(b, c, d) - min(b, c, d)\)。
可以求出:
\(\overline a = d - b\)
\(\overline b = d\)
\(\overline c = d\)
\(\overline d = c\)
可以看出,\(\overline x\) 最大的那两个不可能会是 0。于是按照这个思路,每次对四个元素判断一下,删除不可能是 0 的两个数,然后去没判断的里面加两个数进来再进行判断。
当 \(n\) 为偶数的时候是刚好剩下两个的,当是奇数的时候会多一个,这时候需要添加一个不在集合中的元素进来,再进行操作。
代码:
#include <bits/stdc++.h>
using namespace std;
int T, n;
void solve(){
cin >> n;
vector < pair < int, int> > a;
a.push_back({0, 1});
a.push_back({0, 2});
for (int p = 3; p <= n;){
a.push_back({0, p ++ });
if (p > n){
if (p == n + 1 && (n & 1) ){
int k = 1;
while ( k == a[0].second || k == a[1].second || k == a[2].second ) k ++ ; //不在集合中
a.push_back({0, k});
}
else break;
}
else a.push_back({0, p ++ });
for (int i = 0; i < 4; i ++ ){
cout << "? " << a[(i + 1) % 4].second << " " << a[(i + 2) % 4].second << " " << a[(i + 3) % 4].second << "\n";
cin >> a[i].first;
}
sort(a.begin(), a.end());
a.pop_back();
a.pop_back();
}
cout << "! " << a[0].second << " " << a[1].second << "\n";
}
int main(){
cin >> T;
while (T -- )
solve();
return 0;
}