A - Airplane
题意 找出三数选两数最小相加和
复杂度 O(1)
#include <iostream>
using namespace std;
int main() {
int p, q, r; cin >> p >> q >> r;
int a = p + q;
int b = q + r;
int c = r + p;
cout << min(a, min(b, c));
return 0;
}
B - Balance
题意 在一列数中插一块板使得左边、右边数的和相差最小,求最小值
Tag 前缀和
后缀和
复杂度 O(n)
#include <iostream>
#include <cmath>
using namespace std;
const int N = 102;
int a[N], s[N], S[N];
int main() {
int n; cin >> n;
for (int i = 1; i <= n; i ++) {
cin >> a[i];
s[i] = s[i - 1] + a[i];
}
for (int i = n; i >= 1; i --) {
S[i] = S[i + 1] + a[i];
}
int res = 100;
for (int i = 1; i <= n; i ++) {
res = min(res, abs(s[i] - S[i + 1]));
}
cout << res << endl;
return 0;
}
C - Typical Stairs
题意 走楼梯,但有些台阶破损
Tag dp
复杂度 O(n)
#include <iostream>
using namespace std;
const int N = 1e5 + 2, mod = 1e9 + 7;
int n, m;
int f[N];
int main() {
cin >> n >> m;
f[0] = f[1] = 1;
while (m --) {
int x; cin >> x;
f[x] = -1;
}
for (int i = 2; i < N; i ++) {
if (f[i] == -1) continue;
f[i] = (max(0, f[i - 1]) + max(0, f[i - 2])) % mod;
}
cout << f[n] << endl;
return 0;
}
D - Lamp
题意 一个矩形区域内有障碍物,找到一个点使得向上下左右四个方向衍生的距离和最大,输出最大覆盖的面积
复杂度 O(n^2)
#include <iostream>
using namespace std;
const int N = 2e3 + 2;
int h, w;
char s[N][N];
int ww[N][N], hh[N][N];
int main() {
cin >> h >> w;
for (int i = 0; i < h; i ++) cin >> s[i];
for (int i = 0; i < h; i ++) {
int idx = 0;
for (int j = 0; j < w; j ++) {
if (s[i][j] == '#') {
for (int k = idx; k < j; k ++) ww[i][k] = j - idx;
idx = j + 1;
} else if (j == w - 1) {
for (int k = idx; k < w; k ++) ww[i][k] = w - idx;
}
}
}
for (int i = 0; i < w; i ++) {
int idx = 0;
for (int j = 0; j < h; j ++) {
if (s[j][i] == '#') {
for (int k = idx; k < j; k ++) hh[k][i] = j - idx;
idx = j + 1;
} else if (j == h - 1) {
for (int k = idx; k < h; k ++) hh[k][i] = h - idx;
}
}
}
int res = 0;
for (int i = 0; i < h; i ++) {
for (int j = 0; j < w; j ++) {
res = max(res, hh[i][j] + ww[i][j]);
}
}
cout << res - 1 << endl;
return 0;
}
E - Sum Equals Xor
题意 二进制整数 L
,有多少个非负整数对 a
b
满足 a + b = a ⊕ b ≤ L
,答案 mod 1e9 + 7
Tag dp
复杂度 O(n)
因为异或算法无法产生新的
1
,因此此题不存在进位情况
状态转移方程 f[i][0]
表示二进制数 a + b
前 i
个数和 L
相同,f[i][1]
表示二进制数 a + b
前 i
个数严格小于 L
-
当
a + b
与L
相等时L
当前位为0
时,a = 0, b = 0
L
当前位为1
时,a = 1, b == 0
或a = 0, b = 1
-
当
a + b
严格小于L
时- 前面已经严格小于
L
,a = 1, b == 0
或a = 0, b = 1
或a = 0, b = 0
- 从当前位置开始严格小于
L
,当且仅当L
当前位为1
时,a = 0, b = 0
- 前面已经严格小于
可以简化为
f0
和f1
#include <iostream>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
int main() {
char c;
ll f0 = 1, f1 = 0;
while (scanf("%c", &c) != EOF && (c == '0' || c == '1')) {
f1 = f1 * 3 % mod;
if (c == '1') f1 = (f0 + f1) % mod, f0 = f0 * 2 % mod;
}
cout << (f0 + f1) % mod << endl;
return 0;
}