AtCoder Beginner Contest 011
A
Problem
Given the current month \(m\) , what month is the \(next\) ?
Solutions
The base of month is \(12\) .
m = m - 1
m = (m + 1) % 12
m = m + 1
print(m)
\(((m - 1) + 1) \% 12 + 1 = m \% 12 + 1\)
B
Problem
Given a string \(S\) , modify it to meet the following conditions :
- The first character is capitalized.
- The second to last character is lowecase.
Solutions
std::string s; std::cin >> s;
for (int i = 0; i < (int)s.size(); i++) {
if ('a' <= s[0] && s[0] <= 'z') s[0] = char(s[0] - 'a' + 'A');
else if (i > 0 && 'A' <= s[i] && s[i] <= 'Z') s[i] = char(s[i] - 'A' + 'a');
}
std::cout << s << "\n";
C
Problem
Given a number \(N\) and threr number \(A, B, C\) . Execute the following operations :
- Choose on of the numbers \(1\) , \(2\) of \(3\) and subtract it from \(N\) .
- \(N\) has never been equal to any one of \(A\) , \(B\) or \(C\) .
- Loop operation, but with a maximum of \(100\) operations.
Answer whether \(N\) can become \(0\) ?
Solutions
We just need to use dynamic programming.
dp[considering \(x\)], the minimum number of operations.
Be careful that the initial value is \(dp[N] = [N \in \{A, B, C\}] \ ? \ +\infty \ : \ 0\) .
Finally we check if \(dp[0] \leq 100\) .
There are \(N\) sates, and the time for transtion is \(T(3)\) , the time for checking whether transition is possible is \(\log 3\) .
So the time complexity of DP is \(T(N \times 3 \times \log 3) = O(N)\) .
view
int N; std::cin >> N;
int v[3] = {0}; for (int i = 0; i < 3; i++) std::cin >> v[i];
std::sort(v, v + 3);
auto forbid = [&] (int x) -> bool {
int p = std::lower_bound(v, v + 3, x) - v;
if (p < 3 && x == v[p]) return true;
else return false;
};
std::vector<int> dp(N + 1, 1 << 30);
dp[N] = forbid(N) ? 1 << 30 : 0;
for (int i = N; i >= 0; --i) {
for (int j = 1; j <= 3; j++) {
if (forbid(i) || forbid(i + j)) continue;
if (i + j <= N && dp[i + j] < 1 << 30) {
dp[i] = std::min(dp[i], dp[i + j] + 1);
}
}
}
std::cout << (dp[0] <= 100 ? "YES" : "NO") << "\n";
D
Problem
In the Cartesian coordinate system, there is a starting point \((0, 0)\) and an ending point \((X, Y)\) .
If you are currently at point \((x, y)\) . You can move by juming, and choose one of the following jumping methods with equal probability each time.
- jumping to \((x + D, y)\) .
- jumping to \((x - D, y)\) .
- jumping to \((x, y + D)\) .
- jumping to \((x, y - D)\) .
You should jump exactly \(N\) times. Ask about the possibility of reaching the ending point.
\(-10^{9} \leq X, Y, \leq 10^{9}, N \leq 1000\)
Solutions
First of all, we would better divide \(X\) and \(Y\) by \(D\) . If \(D \mid X\) or \(D \mid Y\) , the possibility of reaching the ending point is \(0\) . And more, we can divide \(X\) by \(D\) and divide \(Y\) by \(D\) .
Second, \(0 \leq |X|, |Y| \leq 10^{9}\) is crazy? If \(|X| + |Y| > N\) there are no solution.
Three, the probability of going left and right is equal, and the probability of going up and down is also equal. So we can make \((X, Y)\) equal to \((|X|, |Y|)\) to aviod negative number as well as somplify the handing of problems.
Using DP to solve it is obvious.
dfs(\(\textbf{remaining number of moves} \ count\), \(nowX\), \(nowY\))
We observe the numbers of states, only \(N \times N \times N = O(N^{3})\) .
So we can use memorize search or Dynamic Programming .
The space should contain \([-N, N]\) so that we allocate the space of \([0, 2 N + 1]\) and define an array offset \(B = N\) .
Dynamic Programming
int N, D, X, Y; std::cin >> N >> D >> X >> Y;
if (X < 0) X *= -1;
if (Y < 0) Y *= -1;
if (X % D != 0 || Y % D != 0) {
std::cout << std::fixed << std::setprecision(12) << 0.L << "\n";
return;
}
X /= D; Y /= D;
if (X + Y > N) {
std::cout << std::fixed << std::setprecision(12) << 0.L << "\n";
return;
}
assert(N <= 200);
int B = N;
std::vector<std::vector<std::vector<db> > > f(2 * N + 1,
std::vector<std::vector<db> > (2 * N + 1,
std::vector<db>(2 * N + 1, -1.L)));
std::function<db(int, int , int)> dfs = [&] (int rem, int x, int y) -> db {
assert(0 <= rem && rem <= N); assert(0 <= B + x && B + x <= 2 * N); assert(0 <= B + y && B + y <= 2 * N);
db &res = f[rem][B + x][B + y];
if (sgn(res) != -1) return res;
else res = 0.L;
if (rem == 0) {
if (x == X && y == Y) return res = 1.L;
else return res = 0.L;
}
int dir[][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
for (int i = 0; i < 4; i++) res += 1.L / 4 * dfs(rem - 1, x + dir[i][0], y + dir[i][1]);
return res;
};
dfs(N, 0, 0);
std::cout << std::fixed << std::setprecision(12) << f[N][B + 0][B + 0] << "\n";
But that's still not enough.
Be aware of the question only needs to be answered in step \(N\) , and the transition probability is symmetric.
The size of sample space is obviously \(4^{N}\) , then wa calculate the size of random event \(\mathbb{A}\) that \(N\)-th step can reach the finish point \(X, Y\) .
If we take \(K \ (0 \leq K \leq N)\) steps in the \(1\)-st dimension, \(A\) steps forward, \(B\) steps backward, we have :
Similarly, we take \(N - K \ (0 \leq K \leq N)\) steps in the \(2\)-st dimension, \(C\) steps forward, \(D\) steps backward, we have :
At the end we get :
The last qustion. If we don't used inverer element, how do we store combination numbers?
We can maintain \(\frac{\binom{n}{m}}{2^{n}}\) by \(\binom{n}{m} = \binom{n - 1}{m - 1} + \binom{n - 1}{m}\) , such that :
So
The bottleneck of time complexity is the preprocessing of combination numbers which \(O(N^{2})\) .
The time complexity of the calculate of the probability is \(O(N)\) .
Math Solution
int N, D, X, Y; std::cin >> N >> D >> X >> Y;
if (X < 0) X *= -1;
if (Y < 0) Y *= -1;
if (X % D != 0 || Y % D != 0) {
std::cout << std::fixed << std::setprecision(12) << 0.L << "\n";
return;
}
X /= D; Y /= D;
if (X + Y > N) {
std::cout << std::fixed << std::setprecision(12) << 0.L << "\n";
return;
}
std::vector<std::vector<db> > f(N + 1, std::vector<db>(N + 1, 0));
f[0][0] = 1;
for (int i = 1, p = 2; i <= N; i++, p *= 2) {
f[i][0] = f[i][i] = f[i - 1][0] / 2;
for (int j = 1; j < i; j++) f[i][j] = (f[i - 1][j - 1] + f[i - 1][j]) / 2;
}
auto check = [&] (int n) -> bool {
return n >= 0 && ~n & 1;
};
db ans = 0;
for (int K = 0; K <= N; K++) {
if (check(K + X) && check(K - X) && check(N - K + Y) && check(N - K - Y)) {
ans += f[N][K] * f[K][(K + X) / 2] * f[N - K][(N - K + Y) / 2];
}
}
std::cout << std::fixed << std::setprecision(12) << ans << "\n";
浙公网安备 33010602011771号