A

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;

int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);

int n;
cin >> n;

for (int i = n; i >= 0; i--) {
cout << i << '\n';
}
return 0;
}

B

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;

int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);

string s;
cin >> s;

if (!(s[0] >= 'A' && s[0] <= 'Z' && s[s.size() - 1] >= 'A' && s[s.size() - 1] <= 'Z')) {
cout << "No\n";
return 0;
}

if (s.size() != 8) {
cout << "No\n";
return 0;
}

for (int i = 1; i <= 6; i++) {
if (!(s[i] >= '0' && s[i] <= '9')) {
cout << "No\n";
return 0;
}
}

if (s[1] == '0') {
cout << "No\n";
return 0;
}


cout << "Yes\n";
return 0;
}

C

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;

int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);

i64 n, T;
cin >> n >> T;

vector<i64> a(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
}

i64 s = accumulate(a.begin() + 1, a.end(), 0LL);
T %= s;
if (s >= T) {
i64 o = 0;
for (int i = 1; i <= n; i++) {
if (T < a[i]) {
cout << i << ' ' << T << '\n';
return 0;
}
T -= a[i];
}
}


return 0;
}

D - Max Multiple

第一次看写了个dfs T爆了,仔细想想,应该用dp

dp[i][j][k] 三维, 表示前i位取了j个数字mod d 等于k的最大和,则

  • 当当前这一位不取, dp[i + 1][j][k] = max(dp[i][j][k]);
  • 否则,如果这一位取了,更新下一位取了j + 1个的时候的值,同时注意mod的数字(详细见代码)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;

int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);

i64 n, k, d;
cin >> n >> k >> d;

vector<i64> a(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
}

vector dp(n + 2, vector (k + 1, vector<i64> (d + 1, -1)));
dp[1][0][0] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= k; j++) {
for (int g = 0; g < d; g++) {
if (dp[i][j][g] == -1) continue;

dp[i + 1][j][g] = max(dp[i + 1][j][g], dp[i][j][g]);

if (j != k) {
dp[i + 1][j + 1][(g + a[i]) % d] = max(dp[i + 1][j + 1][(g + a[i]) % d], dp[i][j][g] + a[i]);
}
}
}
}
cout << dp[n + 1][k][0] << '\n';
return 0;
}

E - Least Elements

  • 题目大意:

给定一个长度为 NN 的整数序列 A=(A1,…,AN)A=(A1​,…,AN​) ,以及整数 MM 和 KK 。
对于每个 i=1,…,N−M+1i=1,…,N−M+1 ,求解如下独立问题。
在 MM 整数 Ai,Ai+1,…,Ai+M−1Ai​,Ai+1​,…,Ai+M−1​ 的排序列表中按升序查找前一个 KK 值的和。

  • 思路: 第一反应是可持久化线段树,维护一个当前位置和区间和,每次查询第(区间长度 - 需要的数字数量小)的数字,合并的时候统计下区间内比当前小的数字的答案。
  • 补题思路: 对顶堆: 开两个堆,将当前满足条件的数置于L中,候选的置于R中,维护一个滑动窗口,每次更新一个值时:将左侧的元素删除,右侧的元素加入,统计最小的k个数的和
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;

int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);

int n, m, k;
cin >> n >> m >> k;

vector<i64> a(n + 1);
for (int i = 1; i<= n; i++) {
cin >> a[i];
}

multiset<i64> l, r;

auto pop_back = [&](multiset<i64>& x) -> i64 {
auto it = prev(x.end());
i64 val = *it;
x.erase(it);
return val;
};

auto pop_front = [&](multiset<i64>& x) -> i64 {
auto it = x.begin();
i64 val = *it;
x.erase(it);
return val;
};

i64 sum = 0;
for (int i = 1; i <= m; i++) {
sum += a[i];
l.insert(a[i]);

while (l.size() > k) {
int v = pop_back(l);
r.insert(v);
sum -= v;
}
}

for (int i = 1; i <= n - m + 1; i++) {
cout << sum << " ";
if (k == m) {
sum += a[i + m] - a[i];
} else {
l.insert(a[i + m]);
sum += a[i + m];

int v = pop_back(l);
sum -= v;
r.insert(v);

if (r.find(a[i]) != r.end()) {
r.erase(r.find(a[i]));
} else {
l.erase(l.find(a[i]));
sum -= a[i];

int v = pop_front(r);
sum += v;
l.insert(v);
}
}
}

return 0;
}

F - Xor Minimization

  • 题目大意
    给定一个长度为n的序列,让你找到一个数字x使得x与序列中所有的数字异或后的最大值最小

  • 思路:
    字典树 : 字典树 | 梦始
    考虑先将所有数字存到一个字典树中,按照每一位进行分析,

  • 如果所有数字的 i 位上都是0, 那么这一位一定填上 0
  • 如果所有数字 i位上都是 1, 那么这一位一定填上1(结果这一位一定是0)
  • 如果某一位上有 0 又有 1, 如 11000, 11100, 第三位不论别的怎么填,异或后答案这一位上总会是1,dfs即可球的答案
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;

struct Trie {
int n, cnt;
vector<array<int, 2>> ch;

Trie() {}
Trie(int n) : n(n), cnt(0) {
ch.assign(n, {});
}

void insert(int x) {
int p = 0;
for (int i = 30; i >= 0; i--) {
int g = ((x >> i) & 1);
if (ch[p][g] == 0) {
ch[p][g] = ++cnt;
}
p = ch[p][g];
}
}

int dfs(int pos, int x) {
if (pos == -1) {
return 0;
}

if (ch[x][0] == 0) {
return dfs(pos - 1, ch[x][1]);
} else if (ch[x][1] == 0) {
return dfs(pos - 1, ch[x][0]);
} else {
return min(dfs(pos - 1, ch[x][0]), dfs(pos - 1, ch[x][1])) | (1LL << pos);
}
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);

int n;
cin >> n;

Trie tr(5e6);
vector<int> a(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
tr.insert(a[i]);
}

int ans = tr.dfs(30, 0);

cout << ans << '\n';
return 0;
}