题解 - [Atcoder ABC 184] (C - F)

比赛链接

C - Super Ryuma

Problem Statement

There is an infinite two-dimensional grid, and we have a piece called Super Ryuma at square \((r_1,c_1)\). (Ryu means dragon and Ma means horse.) In one move, the piece can go to one of the squares shown below:

More formally, when Super Ryuma is at square \((a,b)\), it can go to square \((c,d)\) such that at least one of the following holds:

  • \(a+b=c+d\)
  • \(a-b=c-d\)
  • \(|a-c|+|b-d|≤3\)

Find the minimum number of moves needed for the piece to reach \((r_2,c_2)\) from \((r_1,c_1)\).

Constraints

  • All values in input are integers.
  • \(1≤r_1,c_1,r_2,c_2≤10^9\)

Input

Input is given from Standard Input in the following format:

\(\begin{matrix} r_1&c_1\\ r_2&c_2 \end{matrix}\)

Output

Print the minimum number of moves needed for Super Ryuma to reach \((r_2,c_2)\) from \((r_1,c_1)\).

Sample Input 1

1
2
1 1
5 6

Sample Output 1

1
2

We need two moves - for example, \((1,1)\to(5,5)\to(5,6)\).

Sample Input 2

1
2
1 1
1 200001

Sample Output 2

1
2

We need two moves - for example, \((1,1)\to(100001,100001)\to(1,200001)\).

Sample Input 3

1
2
2 3
998244353 998244853

Sample Output 3

1
3

We need three moves - for example, \((2,3)\to(3,3)\to(-247,253)\to(998244353,998244853)\).

Sample Input 4

1
2
1 1
1 1

Sample Output 4

1
0

解题思路

做这题时我想到了国际象棋中的象,如果两点同色,则必然能在两步内到达

不难发现最多只需三步即可到达

其他的情况简单讨论下即可

代码参考

Show code

AtCoder_abc184_cview raw
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
/*
* @Author: Tifa
* @Description: From <https://github.com/Tiphereth-A/CP-archives>
* !!! ATTENEION: All the context below is licensed under a
* GNU Affero General Public License, Version 3.
* See <https://www.gnu.org/licenses/agpl-3.0.txt>.
*/
#include <bits/stdc++.h>
using namespace std;
int main() {
#define _END(ans) \
{ \
cout << ans; \
return 0; \
}
int a, b, c, d;
cin >> a >> b >> c >> d;
if (a == c && b == d) _END(0);
if (abs(a - c) + abs(b - d) <= 3 || a + b == c + d || a - b == c - d) _END(1);
if ((a + b + c + d) % 2 == 0) _END(2);
for (int i = -3, a1, b1; i <= 3; ++i)
for (int j = -3; j <= 3; ++j) {
if (i + j > 3) continue;
a1 = a + i;
b1 = b + j;
if (abs(a1 - c) + abs(b1 - d) <= 3 || a1 + b1 == c + d ||
a1 - b1 == c - d)
_END(2);
}
_END(3);
}

D - increment of coins

Problem Statement

We have a bag containing \(A\) gold coins, \(B\) silver coins, and \(C\) bronze coins.

Until the bag contains \(100\) coins of the same color, we will repeat the following operation:

Operation: Randomly take out one coin from the bag. (Every coin has an equal probability of being chosen.) Then, put back into the bag two coins of the same kind as the removed coin.

Find the expected value of the number of times the operation is done.

Constraints

  • \(0≤A,B,C≤99\)
  • \(A+B+C≥1\)

Input

Input is given from Standard Input in the following format:

\(A\ B\ C\)

Output

Print the expected value of the number of times the operation is done. Your output will be accepted if its absolute or relative error from the correct value is at most \(10^{-6}\).

Sample Input 1

1
99 99 99

Sample Output 1

1
1.000000000

No matter what coin we take out in the first operation, the bag will contain \(100\) coins of that kind.

Sample Input 2

1
98 99 99

Sample Output 2

1
1.331081081

We will do the second operation only if we take out a gold coin in the first operation. Thus, the expected number of operations is \(2\times\frac{98}{98+99+99}+1\times\frac{99}{98+99+99}+1\times\frac{99}{98+99+99}=1.331081081...\)

Sample Input 3

1
0 0 1

Sample Output 3

1
99.000000000

Each operation adds a bronze coin.

Sample Input 4

1
31 41 59

Sample Output 4

1
91.835008202

解题思路

比较简单的期望 MS

\(f(a,b,c)\) 表示三种硬币各有 \(a,b,c\) 个的时候,胜利的期望步数

\[ f(a,b,c)=\frac{a\ f(a+1,b,c)+b\ f(a,b+1,c)+c\ f(a,b,c+1)}{a+b+c}+1 \]

代码参考

Show code

AtCoder_abc184_dview raw
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
/*
* @Author: Tifa
* @Description: From <https://github.com/Tiphereth-A/CP-archives>
* !!! ATTENEION: All the context below is licensed under a
* GNU Affero General Public License, Version 3.
* See <https://www.gnu.org/licenses/agpl-3.0.txt>.
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 105;
double dp[N][N][N];
double f(int a, int b, int c) {
if (a == 100 || b == 100 || c == 100) return dp[a][b][c] = 0;
if (dp[a][b][c] >= 0) return dp[a][b][c];
return dp[a][b][c] = 1.0 * a / (a + b + c) * f(a + 1, b, c) +
1.0 * b / (a + b + c) * f(a, b + 1, c) +
1.0 * c / (a + b + c) * f(a, b, c + 1) + 1;
}
int main() {
int a, b, c;
cin >> a >> b >> c;
for (int i = a; i < N; ++i)
for (int j = b; j < N; ++j)
for (int k = c; k < N; ++k) dp[i][j][k] = -1;
printf("%.9lf", f(a, b, c));
return 0;
}

E - Third Avenue

Problem Statement

There is a town represented as a two-dimensional grid with \(H\) horizontal rows and \(W\) vertical columns.

A character \(a_{i,j}\) describes the square at the \(i\)-th row from the top and \(j\)-th column from the left. Here, \(a_{i,j}\) is one of the following: S, G, ., #, a, ..., and z.

# represents a square that cannot be entered, and a, ..., z represent squares with teleporters.

Takahashi is initially at the square represented as S. In each second, he will make one of the following moves:

  • Go to a non-# square that is horizontally or vertically adjacent to his current position.
  • Choose a square with the same character as that of his current position, and teleport to that square. He can only use this move when he is at a square represented as a, ..., or z.

Find the shortest time Takahashi needs to reach the square represented as G from the one represented as S. If the destination is unreachable, report -1 instead.

Constraints

  • \(1≤H,W≤2000\)
  • \(a_{i,j}\) is S, G, ., #, or a lowercase English letter.
  • There is exactly one square represented as S and one square represented as G.

Input

Input is given from Standard Input in the following format:

\(\begin{matrix} H&W\\ a_{1,1}&...&a_{1,W}\\ \vdots\\ a_{H,1}&...&a_{H,W} \end{matrix}\)

Output

Print the shortest time Takahashi needs to reach the square represented as G from the one represented as S. If the destination is unreachable from the initial position, print -1 instead.

Sample Input 1

1
2
3
2 5
S.b.b
a.a.G

Sample Output 1

1
4

Let \((i,j)\) denote the square at the \(i\)-th row from the top and \(j\)-th column from the left.

Initially, Takahashi is at \((1,1)\). One way to reach \((2,5)\) in four seconds is:

  • go from \((1,1)\) to \((2,1)\)
  • teleport from \((2,1)\) to \((2,3)\), which is also an a square;
  • go from \((2,3)\) to \((2,4)\);
  • go from \((2,4)\) to \((2,5)\).

Sample Input 2

1
2
3
4
5
6
7
8
9
10
11
12
11 11
S##...#c...
...#d.#.#..
..........#
.#....#...#
#.....bc...
#.##......#
.......c..#
..#........
a..........
d..#...a...
.#........G

Sample Output 2

1
14

Sample Input 3

1
2
3
4
5
6
7
8
9
10
11
12
11 11
.#.#.e#a...
.b..##..#..
#....#.#..#
.#dd..#..#.
....#...#e.
c#.#a....#.
.....#..#.e
.#....#b.#.
.#...#..#..
......#c#G.
#..S...#...

Sample Output 3

1
-1

解题思路

简单的 BFS 会卡一个点,要加优化

注意到任意一个传送门最多都只会经过一次,所以我们可以把经过的传送门销毁

注意一下 std::list<>.erase() 的用法

代码参考

Show code

AtCoder_abc184_eview raw
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
/*
* @Author: Tifa
* @Description: From <https://github.com/Tiphereth-A/CP-archives>
* !!! ATTENEION: All the context below is licensed under a
* GNU Affero General Public License, Version 3.
* See <https://www.gnu.org/licenses/agpl-3.0.txt>.
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 2005;
using map_T = char[N][N];
using ans_T = int[N][N];
struct Point {
int x, y;
Point(int _x = 0, int _y = 0): x(_x), y(_y) {}
Point(const Point &_p): x(_p.x), y(_p.y) {}
Point operator+(const Point &rhs) {
Point ret(*this);
ret.x += rhs.x;
ret.y += rhs.y;
return ret;
}
Point operator+=(const Point &rhs) {
x += rhs.x;
y += rhs.y;
return *this;
}
bool operator==(const Point &rhs) const { return x == rhs.x && y == rhs.y; }
int &get_ans(ans_T &ans_in) { return ans_in[x][y]; }
const char &get_map(const map_T &map_in) const { return map_in[x][y]; }
};
const Point dir[] = {Point(-1, 0), Point(1, 0), Point(0, 1), Point(0, -1)};
int h, w;
map_T maps;
ans_T ans;
bool isvalid(const Point &p) {
return p.x > 0 && p.y > 0 && p.x <= h && p.y <= w && p.get_map(maps) != '#';
}
int main() {
scanf("%d%d\n", &h, &w);
for (int i = 1; i <= h; ++i) scanf("%s", maps[i] + 1);
queue<Point> q;
Point p_end;
list<Point> portals[30];
for (int i = 1; i <= h; ++i)
for (int j = 1; j <= w; ++j) {
if (maps[i][j] == 'S') {
q.push(Point(i, j));
continue;
}
if (maps[i][j] == 'G') {
p_end = Point(i, j);
continue;
}
if (islower(maps[i][j])) {
portals[maps[i][j] - 'a'].push_back(Point(i, j));
continue;
}
}
while (!q.empty()) {
Point now(q.front());
q.pop();
for (const Point &i : dir) {
Point _(now + i);
if (!isvalid(_)) continue;
if (_.get_ans(ans)) continue;
if (_ == p_end) {
cout << now.get_ans(ans) + 1;
return 0;
}
_.get_ans(ans) = now.get_ans(ans) + 1;
q.push(_);
}
if (islower(now.get_map(maps))) {
list<Point> &now_portal = portals[now.get_map(maps) - 'a'];
bool f = 1;
for (auto i = now_portal.begin(); i != now_portal.end(); f ? ++i : i) {
if (*i == now) {
i = now_portal.erase(i);
f = 0;
continue;
}
f = 1;
Point _(*i);
if (!isvalid(_)) continue;
if (_.get_ans(ans)) continue;
if (_ == p_end) {
cout << now.get_ans(ans) + 1;
return 0;
}
i = now_portal.erase(i);
f = 0;
_.get_ans(ans) = now.get_ans(ans) + 1;
q.push(_);
}
}
}
cout << -1;
}

F - Programming Contest

Problem Statement

Takahashi will participate in a programming contest, which lasts for \(T\) minutes and presents \(N\) problems.

With his extrasensory perception, he already knows that it will take Ai minutes to solve the i-th problem.

He will choose zero or more problems to solve from the N problems so that it takes him no longer than \(T\) minutes in total to solve them.

Find the longest possible time it takes him to solve his choice of problems.

Constraints

  • All values in input are integers.
  • \(1≤N≤40\)
  • \(1≤T≤109\)
  • \(1≤A_i≤109\)

Input

Input is given from Standard Input in the following format:

\(\begin{matrix} N&T\\ A_1&...&A_N \end{matrix}\)

Output

Print the answer as an integer.

Sample Input 1

1
2
5 17
2 3 5 7 11

Sample Output 1

1
17

If he chooses the \(1\)-st, \(2\)-nd, \(3\)-rd, and \(4\)-th problems, it takes him \(2+3+5+7=17\) minutes in total to solve them, which is the longest possible time not exceeding \(T=17\) minutes.

Sample Input 2

1
2
6 100
1 2 7 5 8 10

Sample Output 2

1
33

It is optimal to solve all the problems.

Sample Input 3

1
2
6 100
101 102 103 104 105 106

Sample Output 3

1
0

He cannot solve any of the problems.

Sample Input 4

1
2
7 273599681
6706927 91566569 89131517 71069699 75200339 98298649 92857057

Sample Output 4

1
273555143

If he chooses the \(2\)-nd, \(3\)-rd, and \(7\)-th problems, it takes him \(273555143\) minutes in total to solve them.

解题思路

直接查肯定 T, 折半搜索可以

将数据分成两部分,一部分二进制枚举所有可能结果并排序;另一部分二进制枚举,二分查找前一部分结果中满足 " 两部分结果之和 \(<T\)" 的最大结果

复杂度

\(\displaystyle\Theta\left(n\cdot 2^\frac{n}{2}+2^\frac{n}{2}\left(\frac{n}{2}\right)^2\right)\implies O\left(\left(\frac{n}{2}\right)^22^\frac{n}{2}\right)\)

代码参考

Show code

AtCoder_abc184_fview raw
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
/*
* @Author: Tifa
* @Description: From <https://github.com/Tiphereth-A/CP-archives>
* !!! ATTENEION: All the context below is licensed under a
* GNU Affero General Public License, Version 3.
* See <https://www.gnu.org/licenses/agpl-3.0.txt>.
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 40, M = (1 << (N / 2)), OFS = 5;
int a[N + OFS];
i64 b[M + OFS];
int main() {
int n, t;
cin >> n >> t;
for (int i = 0; i < n; ++i) cin >> a[i];
int len = n / 2, len_b = 0;
i64 ans = 0;
for (int i = 0; i < (1 << len); ++i) {
i64 sum = 0;
for (int j = 0; j < len; ++j)
if (i >> j & 1) sum += a[j];
if (sum > t) continue;
b[len_b++] = sum;
ans = max(ans, sum);
}
sort(b, b + len_b);
for (int i = 0; i < (1 << (n - len)); ++i) {
i64 sum = 0;
for (int j = 0; j < n - len; ++j)
if (i >> j & 1) sum += a[len + j];
if (sum > t) continue;
ans = max(ans, sum);
int pos = upper_bound(b, b + len_b, t - sum) - b - 1;
if (pos) ans = max(ans, sum + b[pos]);
}
cout << ans;
return 0;
}