A. XORwice
题意:给定两个整数a, b,对任意的x,求(a⊕x) + (b⊕x)的最小值。
题解:如果 a 和 b 的某一数位是相同的(都为0或都为1),那么x只要在这一位取相同的值就可以让答案的这一数位为0。如果 a 和 b 的某一数位不同(一个是1一个是0),那么无论x在这一位取什么值答案的这一数位都会是1 。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T;
cin >> T;
for (int cas = 0; cas < T; cas++) {
int res = 0;
int a, b, cnt = 0;
cin >> a >> b;
while (a != 0 && b != 0) {
int ta = a & 1, tb = b & 1;
a >>= 1; b >>= 1;
if (ta != tb) {
res += (1 << cnt);
}
cnt++;
}
res += ((a << cnt) + (b << cnt));
cout << res << endl;
}
return 0;
}
B. Putting Bricks in the Wall
题意:给定一个 n×n 的矩阵, 矩阵中的每个元素都是0或1(除了起点和终点),(1,1) 是起点, (n,n)是终点。从起点出发前要选择走0或者走1,如果选0,那么只能走矩阵中值为0的格子,选1只能走值为1的格子。你最多只能翻转两个格子的值(0到1或1到0),使得从起点无法走到终点。
题解:只要让起点旁的两个元素都为0,终点旁的两个元素都为1,或者让起点旁的两个元素都为1,终点旁的两个元素都为0,这时从起点必然走不到终点。情况很少,穷举即可。
#include <bits/stdc++.h>
using namespace std;
char arr[205][205];
int n;
void changeA() {
cout << 1 << ' ' << 2 << endl;
}
void changeB() {
cout << 2 << ' ' << 1 << endl;
}
void changeC() {
cout << n-1 << ' ' << n << endl;
}
void changeD() {
cout << n << ' ' << n-1 << endl;
}
int main()
{
int T;
cin >> T;
for (int cas = 0; cas < T; cas++) {
cin >> n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> arr[i][j];
}
}
int a = arr[0][1] - '0', b = arr[1][0] - '0';
int c = arr[n-2][n-1] - '0', d = arr[n-1][n-2] - '0';
int cnt = 0;
if (a == 0 && b == 0) {
if (d == 0) cnt++;
if (c == 0) cnt++;
cout << cnt << endl;
if (c == 0) changeC();
if (d == 0) changeD();
} else if (a == 0 && b == 1) {
if (c == d) cnt = 1;
else cnt = 2;
cout << cnt << endl;
if (c == 0 && d == 0) changeA();
else if (c == 1 && d == 1) changeB();
else if (c == 0 && d == 1) {
changeA();
changeD();
}else if (c == 1 && d == 0) {
changeA();
changeC();
}
} else if (a == 1 && b == 0) {
if (c == d) cnt = 1;
else cnt = 2;
cout << cnt << endl;
if (c == 0 && d == 0) changeB();
else if (c == 1 && d == 1) changeA();
else if (c == 0 && d == 1) {
changeA();
changeC();
}else if (c == 1 && d == 0) {
changeA();
changeD();
}
} else if (a == 1 && b == 1) {
if (d == 1) cnt++;
if (c == 1) cnt++;
cout << cnt << endl;
if (c == 1) changeC();
if (d == 1) changeD();
}
}
return 0;
}
C. Palindromifier
题意:给定一个长度为n的字符串s。你可以进行两种操作,使得该字符串变为一个回文串。操作1:选择一个 i (2 ≤ i ≤ n−1),将 s2 到 si 的字符串反转后加在原字符串的最前面。(R i)操作2:选择一个 i (2 ≤ i ≤ n−1),将 si 到 sn-1 的字符串反转后加在原字符串的最后面。(L i)
题解:设一个字符串为 abc (a、b、c可替换成其他的字符串)。第一步:R n-1 可得到 abcb 。第二步:L n 可得到 cbabcb 。第三步:L 2 可得到 bcbabcb 。
#include <bits/stdc++.h>
using namespace std;
int main()
{
string s;
cin >> s;
cout << 3 << endl;
cout << "R " << s.size() - 1 << endl;
cout << "L " << s.size() << endl;
cout << "L " << 2 << endl;
return 0;
}
D. Hexagons
题意:给定一个二维蜂窝图,每个格子可以向六个方向移动,每个方向有不同的权值。给出一个格子的坐标(x, y) 问从 (0,0) 到 (x, y) 的最小花费。
题解:c1方向可以直接按c1走,也可以通过c2和c6走到,取最小值,即是c1方向的最小权值。其他方向同理。判断目标点的x和y的值,就可以得出目标点在哪个象限(如x>0且y>0就是第一象限),不同象限可以通过不同的方向走到,分类讨论即可。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
int T; cin >> T;
for (int cas = 0; cas < T; cas++) {
int x, y;
cin >> x >> y;
ll c[7];
for (int i = 1; i <= 6; i++) cin >> c[i];
c[1] = min(c[1], c[6] + c[2]);
c[2] = min(c[2], c[1] + c[3]);
c[3] = min(c[3], c[2] + c[4]);
c[4] = min(c[4], c[3] + c[5]);
c[5] = min(c[5], c[4] + c[6]);
c[6] = min(c[6], c[5] + c[1]);
ll ans = 0;
if (x >= 0 && y >= 0) {
if (x > y) ans = y * c[1] + (x - y) * c[6];
else ans = x * c[1] + (y - x) * c[2];
} else if (x <= 0 && y <= 0) {
if (x < y) ans = -y * c[4] + (y - x) * c[3];
else ans = -x * c[4] + (x - y) * c[5];
} else if (x <= 0 && y >= 0) {
ans = y * c[2] - x * c[3];
} else {
ans = x * c[6] - y * c[5];
}
cout << ans << endl;
}
return 0;
}