牛客周赛 Round 39

IOI赛制,600+,y神 关键思路,C D 题的对 P 取模
D 题是一个完全背包,不优化可过
E 因为边界导致没 a 出来,30 分
F 暴力可以过…

A

签到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N = 2e6 + 10;

int main() {
int n = 0;
vector<ll> nums(6);
ll sum = 0;
for (int i = 0; i < 6; i++) {
cin >> nums[i];
sum += nums[i];
}
if (nums[0] * 30 < sum) {
cout << "Yes" << endl;
} else {
cout << "No" << endl;
}
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
#include <bits/stdc++.h>  

using namespace std;
typedef long long ll;
const int N = 2e6 + 10;

int main() {
ll n = 0, k;
cin >> n >> k;
vector<ll> nums(n);
ll sum = 0;
for (int i = 0; i < n; i++) {
cin >> nums[i];
sum += nums[i];
}
sort(nums.begin(), nums.end(), greater<ll>());
ll yu = sum % k;
if (yu == 0) {
cout << 0 << endl;
return 0;
} for (int i = 0; i < n; i++) {
if (nums[i] <= yu) {
yu -= nums[i];
} else {
yu = 0;
} if (yu == 0) {
cout << i + 1 << endl;
return 0;
} } cout << n << endl;
return 0;
}

C

因为 p == 3 只需要判断三种情况

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
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N = 2e6 + 10;

int main() {
// read file
ll n, p;
cin >> n >> p;
vector<ll> v(n);
for (auto &it: v) {
cin >> it;
it = it % 3;
}

// n 种 food
// value ai
// sum % 3 == 0
// 0 1 2
unordered_map<int, int> M;
for (auto it: v) {
if (it == 0) {
cout << 1 << endl;
return 0;
} else if (it == 1) {
M[1]++;
} else if (it == 2) {
M[2]++;
}
}
if (M.count(1) && M.count(2)) {
cout << 2 << endl;
return 0;
}
if (M.count(1)) {
cout << 3 << endl;
return 0;
}
if (M.count(2)) {
cout << 3 << endl;
return 0;
}
return 0;
}

D

Bfs ,加剪枝,暴力即可过

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
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N = 2e6 + 10;

int main() {
// read file
ll n, p;
cin >> n >> p;
vector<ll> v(n);
set<ll> s;
for (auto &it: v) {
cin >> it;
it = it % p;
s.insert(it);
}
vector<ll> nv;
queue<pair<int, int>> q;
vector<bool> vis(p, false);
for (auto it: s) {
nv.push_back(it);
q.push({it, 1});
vis[it] = true;
}
if (s.count(0)) {
cout << 1 << endl;
return 0;
}

// bfs
while (!q.empty()) {
auto [cur, step] = q.front();
q.pop();
if (cur == 0) {
cout << step << endl;
return 0;
}
for (auto it: nv) {
int to = (cur + it) % p;
if (vis[to]) continue;
q.push({to, step + 1});
vis[to] = true;
}
}
cout << -1 << endl;
return 0;
}

E

求有多少种 1 <= i <= p, 1 <= j <= m, 1 <= k <= p, 注意去重
满足 i x j + 2 x i x k + 2 x j x k == x
思路 枚举+二分找答案

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
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

int main() {
ll n = 0, k, p, ans = 0, x, m;
cin >> n >> m >> p >> x;
unordered_set<ll> s;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
ll l = 1, r = p + 1;
while (l <= r) {
ll mid = l + (r - l) / 2;
if (i * j + 2 * i * mid + 2 * j * mid == x && mid <= p) {
s.insert(i + j * 3001 + 1ll * mid * 3001 * 3001);
break;
} else if (i * j + 2 * i * mid + 2 * j * mid < x) {
l = mid + 1;
} else {
r = mid - 1;
}
}
}
}
cout << s.size() << endl;
}

F

暴力能过,数据很弱

看到有并查集,二分,线段树的解法