Akash and the 122 Assignment Editorial
Difference between en28 and en29, changed 0 character(s)
[Problem A — Akash and the Fortnite String](https://codeforces.net/gym/512940/problem/A)↵

<spoiler summary="Solution">↵
The string `"abababab..."` of length $k + 1$ is a $k$-Fortnite string.↵
Then, set a variable `s = "a"`, and add `"a"` or `"b"` to `s` $k$ times.↵
</spoiler>↵

<spoiler summary="Implementation">↵
~~~~~↵
import sys, math, random↵
input = sys.stdin.readline↵
out = []↵
 ↵
for _ in range(int(input())):↵
    n = int(input())↵
 ↵
    s = "a"↵
    for i in range(k):↵
        if i % 2 == 0:↵
            s += "b"↵
        else:↵
            s += "a"↵

    out.append(s)↵
 ↵
print("\n".join(out))↵
~~~~~↵
</spoiler>↵

[Problem B &mdash; Akash and the Lactation Pod](https://codeforces.net/gym/512940/problem/A)↵

<spoiler summary="Solution">↵
First, sort the array of initial positions $a$.↵

Note that if there are two business majors on consecutive squares, Akash cannot get past them.↵
Thus, we can loop through $a$ and check that no two consecutive elements are consecutive.↵

If there are no business majors blocking the path, Akash can reach the lactation pod in $n - 1$ seconds.↵

If the positions of two consecutive business majors have the same parity, Akash can get by both without pausing. ↵
Otherwise, if they have the same parity, Akash must pause one second to ensure he can move past the second business major.↵
Additionally, if the first business major is on an odd square, Akash must wait a second to get past the first business major.↵

We can keep a variable `curParity` representing the parity of the last processed business major.↵
Initially, `curParity` is set to `0`, representing the fact that if the first business major is on an odd square, Akash must wait a second.↵
Also, keep a counter `pauses` to count how many times Akash must pause.↵

Then, loop through the array $a$.↵
If the position of the next business major has a different parity than `curParity`, then increment `pauses` by $1$ and update `curParity`.↵
Otherwise, Akash does not have to pause, and no action needs to be taken.↵

Then, we can print $n - 1$ added to the number of pauses.↵
</spoiler>↵

<spoiler summary="Implementation">↵
~~~~~↵
import sys↵
input = sys.stdin.readline↵
out = []↵
 ↵
for _ in range(int(input())):↵
    n, m = map(int, input().split())↵
    A = list(map(int, input().split()))↵
    A.sort()↵
 ↵
    for i in range(m - 1):↵
        if A[i] + 1 == A[i+1]:↵
            out.append(-1)↵
            break↵
    else:↵
        curPar = 0↵
        pauses = 0↵
        for x in A:↵
            if x % 2 != curPar:↵
                curPar = x % 2↵
                pauses += 1↵
        ↵
        out.append(n - 1 + pauses)↵
 ↵
print("\n".join(map(str, out)))↵
~~~~~↵
</spoiler>↵

[Problem C &mdash; Akash and the Mycelium Mushrooms](https://codeforces.net/gym/512940/problem/A)↵

<spoiler summary="Solution">↵
Since the limit on $n$ is quite small, we can afford a solution in $O(n^2)$.↵
This means we can loop through all possible swaps.↵

First, let's see how much any given swap adds to the final sum of the heights.↵
Consider swapping $a_i$ and $a_j$.↵
Then, after a week, instead of mushrooms with heights $ia_i$ and $ja_j$, we get mushrooms of heights $ia_j$ and $ja_i$.↵
Thus, the swap contributed $$ia_j + ja_i - (ia_i - ja_j) = i(a_j - a_i) + j(a_i - a_j) = (i - j)(a_i - a_j)$$ to the final sum.↵

We can loop through the array and find the two best swaps, by finding the highest and second highest value of $(i - j)(a_i - a_j)$ over all pairs of indices $(i, j)$.↵
Let the two best swaps be $(i, j)$ and $(h, k)$.↵

Note that if $n = 2$, there is only $1$ possible swap, so we deal with this case separately.↵
Akash's choices are forced, so this should be easy.↵

If these indices are all distinct, then we just need to perform these two swaps.↵

Otherwise, the problem is more interesting.↵
WLOG say they share an index, $i = h$.↵
That is, the two best swaps are $(i, j)$ and $(i, k)$.↵
We can be greedy here: the best sequence of swaps will always involve one of these two swaps (reasoning for this given below).↵
Then, we can make each swap, and go through all possible swaps again, and see what combination gives us the best possible increase.↵


<spoiler summary="Proof sketch for greedy">↵
AFSOC the best sequence of swaps doesn't involve $(i, j)$ or $(i, k)$.↵

If either of the two other swaps are independent of $(i, j)$ and $(i, k)$, then doing $(i, j)$ and the independent swap is guaranteed to be better.↵

We can make a stronger claim: both swaps must use the index $i$. This is because if one of them does not, then since they cannot be independent, they must share an index $j$ or $k$ (WLOG say the other swap shares $j$).↵
Then doing $i, k$ and this other swap will always be better (or $(i, j$ if they share $k$).↵

Thus, both other swaps have to involve index $i$.↵

Next, note that we cannot have $j < i < k$ or $j > i > k$, since then the swap $(j, k)$ would be best.↵
Thus, $i$ is either the smallest or largest index out of $i, j, k$.↵
If $i$ is the smallest, then WLOG let $j < k$.↵
Let the other swaps be $(i, s)$ and $(i, t)$ where $s < t$.↵

Performing the swaps $(i, s)$ and $(i, t)$ effectively reorders the elements $a_i, a_s, a_t \to a_t, a_i, a_s$.↵
The total increase in the final sum is $$ia_t + sa_i + ta_s - (ia_i + sa_s + ta_t) = i(a_t - a_i) + s(a_i - a_s) + t(a_s - a_t).$$↵
Alternatively, performing the two swaps $(i, j)$ and $(i, s)$ reorders these elements $a_i, a_j, a_s \to a_s, a_i, a_j$, which results in an increase of $$ia_s + ja_i + sa_j - (ia_i + ja_j + sa_s) = i(a_s - a_i) + j(a_i - a_j) + s(a_j - a_s).$$↵

We can translate all indices down $i$ without affecting the increase in the sum.↵
Thus, the increases become↵
$$(s - i)(a_i - a_s) + (t - i)(a_s - a_t)$$↵
and↵
$$(j - i)(a_i - a_j) + (s - i)(a_j - a_s).$$↵

Then, compare the first term of the first expression $(s - i)(a_i - a_s)$ and the second term of the second expression $(s - i)(a_j - a_s)$.↵
Clearly, $a_i - a_s > a_j - a_s$ so the second term is larger.↵

Next, compare the remaining two terms $(t - i)(a_s - a_t)$ and $(j - i)(a_i - a_j)$.↵
Again, it is clear that the second is larger.↵

Thus, swapping $(i, j)$ and $(i, s)$ is always better.↵

Hence, it is impossible for the two best swaps not to include one of $(i, j)$ or $(i, k)$.↵
</spoiler>↵

</spoiler>↵

<spoiler summary="Implementation">↵
~~~~~↵
import sys, math↵
input = sys.stdin.readline↵
out = []↵
 ↵
for _ in range(int(input())):↵
    n = int(input())↵
    A = list(map(int, input().split()))↵
    ↵
    if n == 2:↵
        out.append(A[0] + 2 * A[1])↵
    else:↵
        bestScore = -math.inf↵
        bestPair = (0, 0)↵
        secBestScore = -math.inf↵
        secBestPair = (0, 0)↵
        for i in range(n - 1):↵
            for j in range(i+1, n):↵
                score = (A[i] - A[j]) * (j - i)↵
                if score > bestScore:↵
                    secBestScore = bestScore↵
                    secBestPair = bestPair↵
                    bestScore = score↵
                    bestPair = (i, j)↵
                elif score > secBestScore:↵
                    secBestScore = score↵
                    secBestPair = (i, j)↵
 ↵
        s = set((*bestPair, *secBestPair))↵
        if len(s) == 4:↵
            i, j = bestPair↵
            A[i], A[j] = A[j], A[i]↵
            i, j = secBestPair↵
            A[i], A[j] = A[j], A[i]↵
        else:↵
            h, k = bestPair↵
            A[h], A[k] = A[k], A[h]↵
            bS1 = -math.inf↵
            bP1 = (0, 0)↵
            for i in range(n - 1):↵
                for j in range(i+1, n):↵
                    s = (A[i] - A[j]) * (j - i)↵
                    if s > bS1:↵
                        bS1 = s↵
                        bP1 = (i, j)↵
            A[h], A[k] = A[k], A[h]↵
            ↵
            h, k = secBestPair↵
            A[h], A[k] = A[k], A[h]↵
            bS2 = -math.inf↵
            bP2 = (0, 0)↵
            for i in range(n - 1):↵
                for j in range(i+1, n):↵
                    s = (A[i] - A[j]) * (j - i)↵
                    if s > bS2:↵
                        bS2 = s↵
                        bP2 = (i, j)↵
            A[h], A[k] = A[k], A[h]↵
 ↵
            if bestScore + bS1 > secBestScore + bS2:↵
                i, j = bestPair↵
                A[i], A[j] = A[j], A[i]↵
                i, j = bP1↵
                A[i], A[j] = A[j], A[i]↵
            else:↵
                i, j = secBestPair↵
                A[i], A[j] = A[j], A[i]↵
                i, j = bP2↵
                A[i], A[j] = A[j], A[i]↵
 ↵
        t = 0↵
        for i, x in enumerate(A):↵
            t += (i+1) * x↵
        out.append(t)↵
 ↵
print("\n".join(map(str, out)))↵
~~~~~↵
</spoiler>↵

[Problem D &mdash; Akash and THE WAR ROOM](https://codeforces.net/gym/512940/problem/D)↵

<spoiler summary="Solution">↵
Let the binary representation of the initial investment be $2^na_n + 2^{n-1}a_{n-1} + \cdots + 2^2a_2 + 2a_1 + a_0$.↵
The final amount will be:↵

$$2^na_n + 2^{n-1}a_{n-1} + \cdots + 2^2a_2 + 2a_1 + a_0$$↵
$$-(2^{n-1}a_n + 2^{n-2}a_{n-1} + \cdots + 2a_2 + a_1)$$↵
$$+2^{n-2}a_n + 2^{n-3}a_{n-1} + \cdots + a_2$$↵
$$\dots$$↵

Collecting terms, the coefficient of each $a_i$ is an alternating sum of powers of $2$.↵

Let's try to find a closed form for $2^n - 2^{n-1} + 2^{n-2} - \cdots \pm 1$.↵
If $n$ is odd, then this sum ends in $- 1$.↵
Pair each consecutive pair of powers of $2$.↵
Their difference is just the smaller power of $2$.↵
For example, $2^n - 2^{n-1} = 2^{n-1}$.↵
Thus, the alternating sum is $2^{n-1} + 2^{n-3} + \cdots + 1$.↵
This is just a sum of powers of $4$, which can be calculated.↵

If $n$ is even, we can multiply the sum for $n - 1$ by $2$ and add $1$.↵

An easy way to generate these sums is to take the previous sum, multiply it by $2$, and add or subtract $1$.↵
Thus, let's create the array `P` that stores these sums of powers of $2$.↵
The array is initialized as `P = [1]`.↵
The largest alternating power sum we need to compute is when $n = k$, the number of days elapsed.↵
Thus, iterate $k$ times, appending `P[-1] * 2 + 1` or `P[-1] * 2 - 1` to `P`.↵
For reference, here are the first few terms of this array.↵
$$P = [1, 1, 3, 5, 11, 21, 43, 85, \dots].$$↵

We want to find binary coefficients $a_n, a_{n-1}, \dots, a_1, a_0$ such that $a_np_n + a_{n-1}p_{n-1} + \cdots + a_1p_1 + a_0p_0 = x$, where $p_i$ is the $i$-th element of `P` and $x$ is the final amount of the investment.↵

Note that some numbers do not have a unique such representation; for example, $5$ can be represented as $0\cdot 1 + 0\cdot 1 + 0\cdot 3 + 1\cdot 5.$ or $1\cdot 1 + 1\cdot 1 + 1\cdot 3 + 0\cdot 5.$↵

We might notice that the "smaller" elements of $P$ – the elements that were formed by appending `P[-1] * 2 - 1` – can be formed in multiple ways.↵
Sums of these "smaller" elements can also be formed in multiple ways.↵

We can use an inductive argument to show that the following algorithm works, where $k = n$ initially:↵
- If `x` is a "smaller" power, then set $a_k$ to $1$ and $a_{k-1}, a_{k-2}, \dots$ to $0$. Both this number and the number one smaller than this (where $a_k = 0$ and $a_{k-1}, a_{k-2}, \dots = 1$) are possible answers.↵
- Otherwise, if `P[k] < x`, then set $a_k = 1$ and `x -= P[k]`. Decrement $k$ and repeat.↵

In practice, we might keep a variable `val` and add a certain power of `2` to `val` when setting $a_k = 1$, or store the digits $a_i$ in an array `D` (the second approach is implemented below).↵
Also, this algorithm gets finicky at the end, as $1$ is both a "smaller" and "larger" power.↵
In the implementation below, once $x$ becomes less than $3$, we treat it on a case-by-case basis.↵

</spoiler>↵

<spoiler summary="Implementation">↵
~~~~~↵
import sys, math, random↵
input = sys.stdin.readline↵
out = []↵
 ↵
for _ in range(int(input())):↵
    k, q = map(int, input().split())↵
 ↵
    P = [1]↵
    shift = -1↵
    for _ in range(k):↵
        P.append(P[-1] * 2 + shift)↵
        shift *= -1↵
    ↵
    O = set(P[3::2])↵
 ↵
    for _ in range(q):↵
        n = int(input())↵
 ↵
        includeOneBefore = False↵
        D = [(n - 1) // P[-1]]↵
        n = (n - 1) % P[-1] + 1↵
        for curP in reversed(P[2:]):↵
            if n == curP and n in O:↵
                D.append(1)↵
                includeOneBefore = True↵
                break↵
            else:↵
                if n >= curP:↵
                    D.append(1)↵
                    n -= curP↵
                else:↵
                    D.append(0)↵
 ↵
        else:↵
            if n == 1:↵
                D.append(1)↵
                includeOneBefore = True↵
            elif n == 2:↵
                D.append(1)↵
                D.append(1)↵
 ↵
        s = D[0] * 2 ** k↵
        power = 2 ** k↵
        for dig in D[1:]:↵
            s += dig * power↵
            power //= 2↵
 ↵
        if includeOneBefore:↵
            out.append(' '.join(map(str, (s-1, s))))↵
        else:↵
            out.append(str(s))↵
 ↵
print("\n".join(out))↵
~~~~~↵
</spoiler>↵

[Problem E &mdash; Akash and the Matrix](https://codeforces.net/gym/512940/problem/E)↵

<spoiler summary="Solution">↵
Given two elements in the same column, their difference modulo $k - 1$ is invariant.↵
For them to become $0$, this difference must be $0$ modulo $k - 1$.↵
Thus, all we have to do is check that the elements in each column are equivalent modulo $k - 1$.↵
It is possible to use an inductive argument to show that any such matrix can be reduced to a zero matrix.↵

Note, the case when $k = 1$ must be treated separately.↵
</spoiler>↵

<spoiler summary="Implementation">↵
~~~~~↵
import sys, math, random↵
input = sys.stdin.readline↵
out = []↵
 ↵
for _ in range(int(input())):↵
    n, m, k = map(int, input().split())↵
    A = []↵
    for _ in range(n):↵
        A.append(list(map(int, input().split())))↵
    ↵
    if k == 1:↵
        for col in range(m):↵
            r = A[0][col]↵
            for row in range(1, n):↵
                if A[row][col] != r:↵
                    out.append("NO")↵
                    break↵
            ↵
            else:↵
                continue↵
 ↵
            break↵
 ↵
        else:↵
            out.append("YES")↵
    ↵
    elif k == 2:↵
        out.append("YES")↵
 ↵
    else:↵
        for col in range(m):↵
            r = A[0][col] % (k - 1)↵
            for row in range(1, n):↵
                if A[row][col] % (k - 1) != r:↵
                    out.append("NO")↵
                    break↵
            ↵
            else:↵
                continue↵
 ↵
            break↵
 ↵
        else:↵
            out.append("YES")↵
 ↵
print("\n".join(out))↵
~~~~~↵
</spoiler>↵

[Problem F &mdash; Akash and the Coins](https://codeforces.net/gym/512940/problem/F)↵

<spoiler summary="Solution">↵
We can find the total number of "good" pairs by PIE.↵
Then, we can find the total number of pairs with simple combinatorics.↵
We can compare probabilities by doing some algebra on these numbers.↵

Then, we can binsearch on $k$ – if the function is increasing, then $k$ must be higher; otherwise, if the function is decreasing, $k$ must be lower.↵

Also, $k$ is optimized when $k \equiv -1 \pmod{m}$, so we only have to binsearch on these values of $k$.↵
Actually, binsearch won't work unless we only binsearch on these values of $k$.↵

*Technically, this approach is not 100% correct. For example, a test case such as $n = 2$, $m = 4$, $a = [1, 188]$ produces the wrong answer because the function is not smooth. However, such a case is extremely rare and is only possible because of the extreme discrepancy between the two values in the array $a$. None of the test cases test on such a test case (verified by comparing with a brute force algorithm). Either way, the checker only confirms that the participant's answer has a better than or equal probability than this solution, so all this does is give some leeway on extreme edge cases. To make the problem 100% rigorous, perhaps another constraint on the input, such as each $a_i > 10$, would solve the issue.↵
</spoiler>↵

<spoiler summary="Implementation">↵
~~~~~↵
import sys, math, random↵
input = sys.stdin.readline↵
out = []↵
 ↵
def choose2(x):↵
    return x * (x - 1) // 2↵
 ↵
def goodPairProbability(A, s, sChoose2, m, k):↵
    pileSize = s // k↵
    bigPileCount = s % k↵
 ↵
    sameDenomination = sum(map(choose2, A))↵
    samePile = bigPileCount * choose2(pileSize + 1) + \↵
        (k - bigPileCount) * choose2(pileSize)↵
 ↵
    overcounted = 0↵
    for ai in A:↵
        q = ai // k↵
        r = ai % k↵
        overcounted += r * choose2(q + 1) + (k - r) * choose2(q)↵
 ↵
    return sChoose2 - sameDenomination - samePile + overcounted, choose2(s + k // m)↵
 ↵
def findMax(A, m):↵
    s = sum(A)↵
    sChoose2 = choose2(s)↵
    ↵
    if m == 1:↵
        lo = 2↵
    else:↵
        lo = 1↵
    ↵
    if lo * m - 1 >= s:↵
        return s↵
 ↵
    hi = (s + 1) // m↵
 ↵
    while lo < hi:↵
        mid = lo + (hi - lo) // 2↵
        good1, total1 = goodPairProbability(A, s, sChoose2, m, mid * m - 1)↵
        good2, total2 = goodPairProbability(A, s, sChoose2, m, (mid + 1) * m - 1)↵
        if good1 * total2 < good2 * total1:↵
            lo = mid + 1↵
        else:↵
            hi = mid↵
 ↵
    if lo == (s + 1) // m:↵
        good1, total1 = goodPairProbability(A, s, sChoose2, m, lo * m - 1)↵
        good2, total2 = goodPairProbability(A, s, sChoose2, m, s)↵
        if good1 * total2 < good2 * total1:↵
            r = s↵
        else:↵
            r = lo * m - 1↵
    else:↵
        r = lo * m - 1↵
 ↵
    return r↵
 ↵
for _ in range(int(input())):↵
    n, m = map(int, input().split())↵
    A = list(map(int, input().split()))↵
 ↵
    out.append(findMax(A, m))↵
 ↵
print("\n".join(map(str, out)))↵
~~~~~↵
</spoiler>↵

History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
en29 English ow3nL 2024-03-31 09:40:46 0 (published)
en28 English ow3nL 2024-03-31 09:38:24 729
en27 English ow3nL 2024-03-31 09:34:33 11
en26 English ow3nL 2024-03-31 09:32:34 2386
en25 English ow3nL 2024-03-31 09:28:42 1629
en24 English ow3nL 2024-03-31 09:25:09 3433
en23 English ow3nL 2024-03-31 09:07:55 319
en22 English ow3nL 2024-03-31 09:05:44 4
en21 English ow3nL 2024-03-31 09:05:01 2
en20 English ow3nL 2024-03-31 09:04:41 153
en19 English ow3nL 2024-03-31 09:02:13 589
en18 English ow3nL 2024-03-31 08:59:46 2558
en17 English ow3nL 2024-03-31 08:49:18 639
en16 English ow3nL 2024-03-31 08:41:07 1418
en15 English ow3nL 2024-03-31 08:21:27 753
en14 English ow3nL 2024-03-31 08:14:56 4 Tiny change: 'ntributed $$ia_j + j' -> 'ntributed \n\n$$ia_j + j'
en13 English ow3nL 2024-03-31 08:14:30 416
en12 English ow3nL 2024-03-31 08:10:51 845
en11 English ow3nL 2024-03-31 08:08:54 2080
en10 English ow3nL 2024-03-31 07:46:28 2 Tiny change: 'ion">~~~~~\nimport sys' -> 'ion">~~~~~import sys'
en9 English ow3nL 2024-03-31 07:46:17 2 Tiny change: 'entation">\n~~~~~\nimp' -> 'entation">~~~~~\nimp'
en8 English ow3nL 2024-03-31 07:46:02 6
en7 English ow3nL 2024-03-31 07:45:34 29
en6 English ow3nL 2024-03-31 07:44:51 481
en5 English ow3nL 2024-03-31 07:38:57 67
en4 English ow3nL 2024-03-31 07:38:06 6 Tiny change: '### Editorial\n\n#### [Problem A' -> '#### Editorial\n\n[Problem A'
en3 English ow3nL 2024-03-31 07:37:50 105
en2 English ow3nL 2024-03-31 07:35:58 45
en1 English ow3nL 2024-03-31 07:34:03 94 Initial revision (saved to drafts)