Round#593(Div.2)
2019-10-18 / Luo Jinrong   

A - Stones

题意

有三堆石头,两种操作:

  • 取出第一堆一个石头和第二堆两个石头
  • 取出第二堆一个石头和第三堆两个石头

问用这两种操作最多能取出多少石头。

做法

贪心。因为两种操作执行一次都会取出三个石头,而第二堆石头在两种操作都会被取出石头,所以我们想要让第二堆石头尽可能多的承受操作。由于第二种操作只消耗一个第二堆中的石头,所以我们先尽可能多的先执行第二种操作,然后再去执行第一种操作。

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<bits/stdc++.h>
using namespace std;
int main() {
int T;
cin >> T;
while (T--) {
int a, b, c, ans = 0;
cin >> a >> b >> c;
ans = min(b, c / 2);
b -= ans, c -= ans * 2;
ans += min(a, b / 2);
cout << ans * 3 << "\n";
}
}

B - Alice and the List of Presents

题意

有$n$种礼物(数量无限),要装到$m$个盒子里面。对于每个盒子能装$0$到$n$种礼物,但是每种礼物只能装一个。最后要使这$m$个盒子里面存在所有$n$种礼物,问方案数。

做法

推导。对于每种礼物单独考虑,比如对于第一种礼物,它出现在第$1$个盒子,第$2$个盒子,…第$m$个盒子;第

$1$、$2$个盒子,第$1$、$3$个盒子,…第$n-1$,$n$个盒子;…第$1$、$2$、…$n$个盒子。总共有$2^m-1$种情况,那么对于$n$种礼物则有$(2^m-1)^n$种方案。

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod(1e9 + 7);
ll qpow(ll a, ll b) {
ll r = 1, base = a;
while (b) {
if (b % 2) {
r = r * base%mod;
}
base = base * base%mod;
b >>= 1;
}
return r%mod;
}
int main() {
ll n, m, ans;
cin >> n >> m;
ans = qpow(qpow(2ll, m) - 1, n) % mod;
cout << ans << "\n";
}

C - Labs

题意

有$n^2$个数,分别为$1$到$n^2$,将他们分到$n$个集合里,每个集合有$n$个数。对于集合$A$,$B$,$f(A,B)$表示$A$中数大于$B$中数的对数。构造出这$n$个集合,使所有集合两两之间$f(A,B)$的最小值最大。

做法

对于两个$n$个元素的集合,其中元素两两配对有$n^2$种,所以$f(A,B)=n^2-f(B,A)$,要使两两之间$f(A,B)$最小值最大,只有$f(A,B)$,$f(B,A)$尽可能相等($n^2$为偶数时相等,奇数时差$1$)。构造方法见代码。

AC代码

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
#include<bits/stdc++.h>
using namespace std;
const int maxn(305);
int lab[maxn][maxn], n;
int main() {
cin >> n;
if (n % 2) {
for (int j = 1; j <= n; j++) {
for (int i = 1; i <= n; i++) {
if (j % 2) {
lab[i][j] = n * n - ((j - 1)*n + i - 1);
}
else {
lab[n - i + 1][j] = n * n - ((j - 1)*n + i - 1);
}
}
}
}
else {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n / 2; j++) {
lab[i][j] = n * n - ((i - 1)*n/2 + j - 1);
}
}
for (int i = 1; i <= n; i++) {
for (int j = n / 2 + 1; j <= n; j++) {
lab[i][j] = (i - 1)*n / 2 + j - n / 2;
}
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cout << lab[i][j] << " \n"[j == n];
}
}
}

D - Alice and the Doll

题意

一个$n*m$的矩阵,其中有$k$个障碍物,问从$(1,1)$出发能否走完所有无障碍物的格子(每个空格只能走一次且在一个空格上只能右转一次不能左转)。

做法

模拟。模拟走的过程,一直直走遇到障碍物或边界右转继续走,直到无法行动。记录走过的空格数,最后若等于$n*m-k$则可以走完,否则不可以。

AC代码

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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn(1e5 + 5);
ll n, m, k, ans = 1, l, r, u, b;
struct ob
{
ll x, y;
}obsx[maxn], obsy[maxn];

bool cmpx(ob a, ob b) {
if (a.x == b.x) {
return a.y < b.y;
}
else {
return a.x < b.x;
}
}

bool cmpy(ob a, ob b) {
if (a.y == b.y) {
return a.x < b.x;
}
else {
return a.y < b.y;
}
}

bool cmp1(ob a, ob b) {
return a.x < b.x;
}

bool cmp2(ob a, ob b) {
return a.y < b.y;
}

int main() {
cin >> n >> m >> k;
l = 0, r = m + 1, u = 1, b = n + 1;
for (int i = 1; i <= k; i++) {
cin >> obsx[i].x >> obsx[i].y;
obsy[i].x = obsx[i].x, obsy[i].y = obsx[i].y;
}
sort(obsx + 1, obsx + k + 1, cmpx);
sort(obsy + 1, obsy + k + 1, cmpy);
int direct = 1;
ob now = { 1,1 }, *fi;
while (1) {
if (direct == 1) {
fi = lower_bound(obsx + 1, obsx + k + 1, now, cmpx);
if (fi->x == now.x) {
r = min(r, fi->y);
}
ans += r - now.y - 1;
if (now.y == r - 1) {
if (now.x == 1 && now.y == 1) {
direct = 2;
}
else {
break;
}
}
else {
now.y = --r;
direct = 2;
}
}
else if (direct == 2) {
fi = lower_bound(obsy + 1, obsy + k + 1, now, cmpy);
if (fi->y == now.y) {
b = min(b, fi->x);
}
if (b - 1 == now.x) {
break;
}
else {
ans += b - now.x - 1;
now.x = --b;
direct = 3;
}
}
else if (direct == 3) {
fi = upper_bound(obsx + 1, obsx + k + 1, now, cmpx);
if ((fi - 1)->x == now.x) {
l = max(l, (fi - 1)->y);
}
if (l + 1 == now.y) {
break;
}
else {
ans += now.y - l - 1;
now.y = ++l;
direct = 4;
}
}
else if (direct == 4) {
fi = upper_bound(obsy + 1, obsy + k + 1, now, cmpy);
if ((fi - 1)->y == now.y) {
u = max(u, (fi - 1)->x);
}
if (u + 1 == now.x) {
break;
}
else {
ans += now.x - u - 1;
now.x = ++u;
direct = 1;
}
}
}
if (ans == m * n - k) {
cout << "Yes\n";
}
else {
cout << "No\n";
}
}

return 0;


本文链接:
https://luojinrong.github.io/2019/10/18/Round-593-Div-2/