I hope you all enjoyed the contest!
| Predictor | A | B | C | D | E | F | G |
|---|---|---|---|---|---|---|---|
| AksLolCoding | 800 | 900 | 1000 | 1500 | 1500 | 1800 | 1700 |
| __baozii__ | 800 | 800 | 1200 | 1500 | 1500 | 1600 | 1900 |
| DivinePunishment | 800 | 900 | 1100 | 1400 | 1500 | 1600 | 1900 |
| Edeeva | 800 | 800 | 1000 | 1200 | 1600 | 1800 | 2200 |
| efishel | 800 | 800 | 1000 | 1200 | 1400 | 1500 | 1900 |
| -firefly- | 800 | 800 | 900 | 1400 | 1500 | 1700 | 2000 |
| beaten_by_ai | 800 | 900 | 1100 | 1600 | 1500 | 1800 | 2000 |
| Hori | 800 | 800 | 1200 | 1600 | 1400 | 1500 | 2000 |
| kevlu8 | 800 | 900 | 1000 | 1300 | 1600 | 1700 | — |
| Lilypad | 800 | 900 | 1100 | 1400 | 1400 | 1500 | — |
| Friedrich | 800 | 800 | 1000 | 1300 | 1600 | 1700 | 2100 |
| macaquedev | 800 | 900 | 800 | 900 | 1500 | 1600 | 1600 |
| Non-origination | 800 | 800 | 1200 | 1500 | 1500 | 1800 | 2100 |
| Proof_by_QED | 800 | 1000 | 1100 | 1400 | 1600 | 1800 | 2100 |
| reirugan | 800 | 800 | 1100 | 1400 | 1600 | 1700 | 2000 |
| SpyrosAliv | 800 | 800 | 1200 | 1800 | 1500 | 1700 | — |
| yse | 800 | 900 | 1000 | 1200 | 1500 | 1700 | — |
| Average | 800.0 | 852.9 | 1058.8 | 1388.2 | 1511.8 | 1676.5 | 1961.5 |
| Actual | 800 | 800 | 1000 | 1200 | 1400 | 1700 | 2100 |
A — Blackboard Game
Alice can't lose unless there are no numbers remaining on her turn (in particular, this can only occur if $$$n$$$ is even). So Bob's job is to pair all numbers into disjoint pairs $$$(a, b)$$$ with $$$a+b\equiv 3\pmod 4$$$. If he can do so, he wins by choosing the paired number to each of Alice's choices. Otherwise, Alice wins.
It doesn't really matter if Bob chooses, say, $$$0$$$ or $$$4$$$, because it won't affect the value of $$$a+b\pmod 4$$$. That is, two values are essentially identical in this game if they are equivalent $$$\bmod 4$$$. So now, the numbers on the blackboard are essentially $$$0, 1, 2, 3, 0, 1, 2, 3, \dots (n-1)\pmod 4$$$.
Now, all of the numbers on the blackboard are either $$$0$$$, $$$1$$$, $$$2$$$, or $$$3$$$. It is clear that Bob must pair $$$0$$$ with $$$3$$$, and $$$1$$$ with $$$2$$$. So Bob wins if the number of $$$0$$$'s is the same as the number of $$$3$$$'s, and the number of $$$1$$$'s is the same as the number of $$$2$$$'s.
#include <bits/stdc++.h>
using namespace std;
void solve(){
int n;
cin >> n;
vector<int> cnt(4);
for(int i=0; i<n; i++)
cnt[i % 4]++;
cout << (cnt[0] == cnt[3] && cnt[1] == cnt[2] ? "Bob" : "Alice") << '\n';
}
int main(){
int t;
cin >> t;
while(t--) solve();
}
For an $$$O(1)$$$ solution, observe that as $$$n$$$ increases, a $$$0$$$, $$$1$$$, $$$2$$$, and $$$3$$$ are introduced, in that order. So the number of $$$0$$$'s can only match the number of $$$3$$$'s, and the number of $$$1$$$'s can only match the number of $$$2$$$'s, if $$$n$$$ is a multiple of $$$4$$$.
#include <bits/stdc++.h>
using namespace std;
void solve(){
int n;
cin >> n;
cout << (n % 4 ? "Alice" : "Bob") << '\n';
}
int main(){
int t;
cin >> t;
while(t--) solve();
}
B — Tournament
If $$$k \gt 1$$$, then the answer is always $$$\texttt{YES}$$$. This is because player $$$j$$$ might never get picked.
If $$$k=1$$$, then we claim that the answer is only $$$\texttt{YES}$$$ if player $$$j$$$ has the maximum strength across all players. Indeed, consider the set of players with maximum strength. It is impossible for all of them to get eliminated, because the last one of them can't possibly lose a match. So at least one of these players will be remaining at the end of the game. If player $$$j$$$ is not one of these players, they cannot be the last player remaining.
#include <bits/stdc++.h>
using namespace std;
void solve(){
int n, j, k, mx = 0;
cin >> n >> j >> k;
vector<int> a(n+1);
for(int i=1; i<=n; i++){
cin >> a[i];
mx = max(mx, a[i]);
}
cout << (k > 1 || a[j] == mx ? "YES" : "NO") << '\n';
}
int main(){
int t;
cin >> t;
while(t--) solve();
}
C — Prefix Min and Suffix Max
If $$$a$$$ has size $$$2$$$, we can make either of its elements the last one. We can transform $$$a$$$ into $$$\min(a_1, a_2)$$$ by choosing the prefix of size $$$2$$$, and we can transform $$$a$$$ into $$$\max(a_1, a_2)$$$ by choosing the suffix of size $$$2$$$.
If $$$a_i$$$ is a prefix min, now we can transform $$$a$$$ into $$$[a_i]$$$. We do so by first choosing the prefix of length $$$i$$$. Now, $$$a_i$$$ is the first element of $$$a$$$. If $$$a$$$ is of size $$$1$$$, we are done. Otherwise, we can choose the suffix consisting of all of the elements after it. Now, our array is of size $$$2$$$, so we can transform $$$a$$$ into $$$[a_i]$$$ as desired. By identical reasoning, if $$$a_i$$$ is a suffix max, we can transform $$$a$$$ into $$$[a_i]$$$.
Now, suppose that $$$a_i$$$ is not a prefix min or a suffix max. Then let $$$a_p$$$ be the min of the prefix $$$[a_1, \dots, a_i]$$$, and let $$$a_s$$$ be the max of the suffix $$$[a_i, \dots, a_n]$$$. Note that $$$p \lt i \lt s$$$ and $$$a_p \lt a_i \lt a_s$$$.
We claim that it is impossible to remove $$$a_p$$$ or $$$a_s$$$ without removing $$$a_i$$$. Consider the first operation which removes (at least) one of $$$a_p$$$, $$$a_i$$$, or $$$a_s$$$.
- Suppose you remove $$$a_p$$$ by choosing a prefix which includes an element smaller than $$$a_p$$$. Since $$$a_p$$$ is the smallest element in $$$[a_1, \dots, a_i]$$$, this means that you must have chosen at least one element after $$$a_i$$$. But then this prefix also includes $$$a_i$$$. Since $$$a_i$$$ is not the min of this prefix, it will also be removed. By identical reasoning, if you remove $$$a_s$$$ by choosing a suffix which includes an element larger than $$$a_s$$$, then $$$a_i$$$ will also be removed.
- Conversely, suppose you remove $$$a_p$$$ by choosing a suffix which includes $$$a_p$$$. But then this suffix will include $$$a_i$$$ and $$$a_s$$$. Since $$$a_i$$$ is not the max of this suffix, it will also be removed. By identical reasoning, if you remove $$$a_s$$$ by choosing a prefix which includes $$$a_s$$$, then $$$a_i$$$ will also be removed.
So the first operation that removes one of $$$a_p$$$, $$$a_i$$$, or $$$a_s$$$ will necessarily remove $$$a_i$$$, so it is impossible to transform $$$a$$$ into $$$[a_i]$$$.
#include <bits/stdc++.h>
using namespace std;
void solve(){
int n;
cin >> n;
vector<int> a(n+1), pre(n+1, INT_MAX), suf(n+2);
for(int i=1; i<=n; i++){
cin >> a[i];
pre[i] = min(pre[i-1], a[i]);
}
for(int i=n; i>=1; i--)
suf[i] = max(suf[i+1], a[i]);
for(int i=1; i<=n; i++)
cout << (a[i] == pre[i] || a[i] == suf[i] ? 1 : 0);
cout << '\n';
}
int main(){
int t;
cin >> t;
while(t--) solve();
}
D — Binary String Battle
Let $$$\mathrm{cnt}$$$ be the number of ones in $$$s$$$. Then clearly if $$$\mathrm{cnt} \leq k$$$, Alice can win immediately.
Now, let's reframe Bob's win condition. Bob can win if and only if he can ensure that, before each of Alice's turns, there are at least $$$k+1$$$ ones in $$$s$$$. In other words, he has to ensure that after each of his turns, $$$\mathrm{cnt} \gt k$$$. Clearly, after each of Bob's turns, $$$\mathrm{cnt} \geq k$$$, since the entire substring he chose is all ones. So he only has to ensure that there is at least one other extra one in $$$s$$$.
If $$$\mathrm{cnt} \gt k$$$ and $$$n\geq 2\cdot k$$$, then Bob can always win. Indeed, on each of Bob's turns, he can pick any existing one in $$$s$$$ to be the extra one. Now, he simply has to choose a substring which doesn't contain this extra one. Then there will be at least $$$k+1$$$ ones; the $$$k$$$ from the substring he chose, and the extra one. If $$$n\geq 2\cdot k$$$, then there must be at least $$$k$$$ elements to either the left or the right of this one, so Bob can choose such a substring.
For example, consider $$$n=8$$$ and $$$k=4$$$. Suppose, before Bob's turn, $$$s=00100010$$$. Then Bob chooses any arbitrary existing one in $$$s$$$, say, the one in the third position. Now, he would like to choose a substring of length $$$k$$$ which does not include the third position. In this case, he can choose the substring $$$s[5, 8]$$$. Now, after his turn, $$$s=00101111$$$. As desired, there are at least five ones, in particular, the four in $$$s[5, 8]$$$ and the extra one in the third position.
This motivates Alice's strategy as well. Suppose that $$$n \lt 2\cdot k$$$. Alice would like to make sure that Bob is losing value from his moves. Notice that every substring of length $$$k$$$ includes the element $$$s_k$$$. So, after Bob's first turn, we have that $$$s_k=1$$$. Now, a winning strategy for Alice is to leave $$$s_k=1$$$ until her last turn, and otherwise choose any $$$k$$$ arbitrary ones to flip. This guarantees that after every round, $$$\mathrm{cnt}$$$ decreases, because Alice flips $$$k$$$ ones, whereas Bob flips at most $$$k-1$$$ zeros, since $$$a_k$$$ is already one. Since $$$\mathrm{cnt}$$$ is nonnegative, finite, and decreasing, it must eventually reach zero.
For example, consider $$$n=8$$$ and $$$k=5$$$. Suppose that before Alice's turn, $$$s=01111101$$$. Then we have that $$$\mathrm{cnt}=6$$$. Alice wants to choose any $$$5$$$ ones to flip, except for $$$s_5$$$. So she chooses to flip $$$s_2$$$, $$$s_3$$$, $$$s_4$$$, $$$s_6$$$, and $$$s_8$$$. Now, before Bob's turn, $$$s=00001000$$$. But any substring of length $$$5$$$ includes $$$s_5$$$, so Bob can only flip at most $$$4$$$ zeros. Suppose he chooses $$$s[2, 6]$$$. Then after his turn, we have that $$$s=01111100$$$. During this round, the value of $$$\mathrm{cnt}$$$ decreased from $$$6$$$ to $$$5$$$, as desired.
#include <bits/stdc++.h>
using namespace std;
void solve(){
int n, k, cnt = 0;
string s;
cin >> n >> k >> s;
for(char c : s)
if(c == '1')
cnt++;
cout << (cnt <= k || n < 2*k ? "Alice" : "Bob") << '\n';
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
int t;
cin >> t;
while(t--) solve();
}
E — MEX Count
Let $$$\mathrm{mex}$$$ be the original $$$\mathrm{MEX}$$$ of $$$a$$$. Clearly we cannot increase $$$\mathrm{MEX}(a)$$$ by removing elements. So, for every $$$0\leq i\leq \mathrm{mex}$$$, let's try to determine, for which $$$k$$$ can we make $$$\mathrm{MEX}(a) = i$$$?
We must have $$$i\leq n-k$$$, since the $$$\mathrm{MEX}$$$ of an array cannot be greater than its size. Furthermore, we must have $$$\mathrm{freq}(i) \leq k$$$, since we have to remove all instances of $$$i$$$ in order to make it the $$$\mathrm{MEX}$$$ of $$$a$$$.
Now, we claim that these are the only constraints. Indeed, suppose that $$$0\leq i\leq \mathrm{mex}$$$, $$$i\leq n-k$$$, and $$$\mathrm{freq}(i) \leq k$$$. We want to choose $$$n-k$$$ elements to keep. Since $$$i\leq \mathrm{mex}$$$, every element smaller than $$$i$$$ is in $$$a$$$, and since $$$i\leq n-k$$$, we can first choose one instance of every element less than $$$i$$$. Now, the $$$\mathrm{MEX}$$$ of our chosen elements is $$$i$$$, so we just need to choose the rest of the elements without affecting the $$$\mathrm{MEX}$$$. We can just choose elements arbitrarily, as long as we don't choose $$$i$$$. Since $$$\mathrm{freq}(i) \leq k$$$, we have enough spare elements to reach our $$$n-k$$$ quota without needing to choose $$$i$$$.
Let's maintain a set of elements which can be $$$\mathrm{MEX}(a)$$$ after removing $$$k$$$ elements. As $$$k$$$ increases, how does this set change? If we compare the set from $$$k-1$$$ to $$$k$$$, we now have that the value $$$n-(k-1)$$$ is no longer legal, since $$$n-(k-1) \gt n-k$$$, so let's erase this element from our set. Furthermore, any elements with frequency $$$k$$$ might now be legal, so let's add them to our set as long as they are $$$\leq \min(\mathrm{mex}, n-k)$$$. Then we output the size of our set.
#include <bits/stdc++.h>
using namespace std;
void solve(){
int n;
cin >> n;
vector<int> a(n);
map<int, int> freq;
set<int> excl;
for(int i=0; i<=n; i++)
excl.insert(i);
for(int i=0; i<n; i++){
cin >> a[i];
freq[a[i]]++;
excl.erase(a[i]);
}
map<int, vector<int>> invfreq;
for(pair<int, int> p : freq)
invfreq[p.second].push_back(p.first);
int mex = *excl.begin();
set<int> vals;
vals.insert(mex);
for(int k=0; k<=n; k++){
vals.erase(n-k+1);
for(int i : invfreq[k])
if(i <= min(mex, n-k))
vals.insert(i);
cout << vals.size() << (k != n ? ' ' : '\n');
}
}
int main(){
int t;
cin >> t;
while(t--) solve();
}
Let $$$\mathrm{ans}_k$$$ be the number of possible values of $$$\mathrm{MEX}(a)$$$ after removing $$$k$$$ elements from $$$a$$$. Now, let $$$\mathrm{diff}$$$ be the difference array of $$$\mathrm{ans}$$$; that is, $$$\mathrm{diff}_k = \mathrm{ans}_k - \mathrm{ans}_{k-1}$$$. Then for all $$$0\leq i\leq \mathrm{mex}$$$, we have that $$$\mathrm{MEX}(a)$$$ can be $$$i$$$ if and only if $$$\mathrm{freq}(i) \leq k \leq n-i$$$. So we increment $$$\mathrm{diff}_{\mathrm{freq}(i)}$$$ and decrement $$$\mathrm{diff}_{n-i+1}$$$. Finally, we can reconstruct $$$\mathrm{ans}$$$ by taking the prefix sums of $$$\mathrm{diff}$$$.
#include <bits/stdc++.h>
using namespace std;
void solve(){
int n;
cin >> n;
vector<int> a(n), ans(n+1), diff(n+2);
map<int, int> freq;
for(int i=0; i<n; i++){
cin >> a[i];
freq[a[i]]++;
}
for(int i=0; i<=n; i++){
diff[freq[i]]++;
diff[n-i+1]--;
if(!freq[i])
break;
}
for(int k=0; k<=n; k++){
ans[k] = (k ? ans[k-1] : 0) + diff[k];
cout << ans[k] << (k != n ? ' ' : '\n');
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
int t;
cin >> t;
while(t--) solve();
}
F — Minimize Fixed Points
Let's first find out which values must be fixed points. Clearly if $$$i$$$ is relatively prime to every $$$1\leq j\leq n$$$ with $$$j\neq i$$$, then $$$i$$$ must be a fixed point. This occurs when $$$i=1$$$, or when $$$i$$$ is prime and $$$2\cdot i \gt n$$$, because the smallest number that is not relatively prime to prime $$$i$$$ is $$$2\cdot i$$$.
Now, let's try to construct $$$p$$$ such that these are the only fixed points. Consider the cycle decomposition of $$$p$$$. If we can ensure that all elements in a cycle, excluding the cycle $$$(1)$$$, share a common divisor greater than $$$1$$$, then $$$p$$$ is good.
Notice that a fixed point corresponds to a cycle of length $$$1$$$. So we want as few cycles of length $$$1$$$ as possible. The prime $$$i$$$ are the most restrictive. Let's pair all prime $$$i$$$ with $$$2\cdot i$$$, if possible. Now, none of the primes $$$\leq \frac{n}{2}$$$ are fixed points. For the remaining composites, we have a lot more freedom. We can insert them into the cycle with any one of their prime factors; now, the composites are also not fixed points. Then all cycles share a common divisor, namely, the prime in that cycle, so $$$p$$$ is good.
One systematic way to do this is to partition the elements from $$$1$$$ to $$$n$$$ based on their largest prime divisor. Then, indeed, all of the elements in the cycle containing prime $$$i$$$ are divisible by $$$i$$$, and $$$2\cdot i$$$ has largest prime factor $$$i$$$, so if $$$2\cdot i \leq n$$$, it will be in the cycle containing $$$i$$$.
#include <bits/stdc++.h>
using namespace std;
vector<bool> comp(1e5+1);
vector<int> primes;
void sieve(){
for(int i=2; i*i<=1e5; i++)
if(!comp[i])
for(int j=i*i; j<=1e5; j+=i)
comp[j] = true;
for(int i=2; i<=1e5; i++)
if(!comp[i])
primes.push_back(i);
}
void solve(){
int n;
cin >> n;
vector<int> p(n+1);
for(auto it = primes.rbegin(); it != primes.rend(); ++it){
vector<int> cycle;
for(int i=*it; i<=n; i+=*it)
if(!p[i])
cycle.push_back(i);
for(int i=0; i<cycle.size(); i++)
p[cycle[i]] = cycle[(i+1) % cycle.size()];
}
for(int i=1; i<=n; i++)
if(!p[i])
p[i] = i;
for(int i=1; i<=n; i++)
cout << p[i] << (i != n ? ' ' : '\n');
}
int main(){
sieve();
int t;
cin >> t;
while(t--) solve();
}
G — Modular Sorting
Let's first try to answer a query of type 2 in $$$O(n)$$$. We want to set $$$a_1$$$ as small as possible. Then we want to set $$$a_2$$$ to the smallest value which is $$$\geq a_1$$$. We continue to choose elements greedily, selecting the smallest legal value $$$a_i$$$ which is $$$\geq a_{i-1}$$$. If at any point there are no legal values, the answer is $$$\texttt{NO}$$$. Otherwise, the answer is $$$\texttt{YES}$$$.
Now, let's try to characterize what values we can change $$$a_i$$$ into. Clearly $$$a_i\pmod{\gcd(k, m)}$$$ is invariant across operations.
Next, we claim that all values less than $$$m$$$ which are congruent to $$$a_i\pmod{\gcd(k, m)}$$$ are reachable.
First, let's consider the case where $$$\gcd(k, m) = 1$$$. Then we can set $$$a_i := a_i + 1\pmod m$$$ by applying the operation onto $$$a_i$$$, $$$x$$$ times, where $$$x$$$ is the modular multiplicative inverse of $$$k\pmod m$$$. By repeatedly adding $$$1$$$, we can set $$$a_i$$$ to any value.
Next, let's consider the case where $$$\gcd(k, m) \gt 1$$$. Then, if we imagine dividing $$$k$$$ and $$$m$$$ by $$$\gcd(k, m)$$$, we fall into the previous case; that is, we can set $$$a_i := a_i + \gcd(k, m)\pmod m$$$ by applying the operation onto $$$a_i$$$, $$$x$$$ times, where $$$x$$$ is the modular multiplicative inverse of $$$\frac{k}{\gcd(k, m)}\pmod{\frac{m}{\gcd(k, m)}}$$$. By repeatedly adding $$$\gcd(k, m)$$$, we can set $$$a_i$$$ to any value which falls into the same congruence class $$$\bmod{\gcd(k, m)}$$$.
Let's try simulating the greedy process, where we repeatedly choose the smallest value which lies in the same congruence class $$$\bmod \gcd(k, m)$$$. Then if we have $$$a_n \lt m$$$, we can sort the array.
However, we want to represent the array in a way such that we can update $$$a_i$$$ quickly, and check the end-result of $$$a_n$$$ after our greedy process quickly. Let $$$\mathrm{diff}$$$ be the difference array of $$$a$$$; that is, $$$\mathrm{diff}_i = a_i - a_{i-1}$$$ (for convenience, we will define $$$a_0 = 0$$$). Then, by telescoping sum, we have that $$$a_n$$$ is the sum of the elements of the difference array; that is, $$$a_n = (a_n - a_{n-1}) + (a_{n-1} - a_{n-2}) + \dots + (a_2 - a_1) + (a_1 - a_0)$$$.
Now, notice that $$$\mathrm{diff}_i$$$ is invariant $$$\bmod{\gcd(k, m)}$$$, and we also must have that $$$\mathrm{diff}_i$$$ is nonnegative for $$$a$$$ to be nondecreasing. So let's maintain the sum of the elements of the difference array, where each element is taken $$$\bmod{\gcd(k, m)}$$$, for each $$$k$$$. Then this is the final value of $$$a_n$$$ after simulating the greedy process. This is quick to update, since only two elements of the difference array are changed with each update.
Finally, we observe that $$$\gcd(k, m)$$$ is always a divisor of $$$m$$$, so we only have to maintain and update $$$d(m)$$$ different values. This allows us to answer queries in $$$O(d(m))$$$ time.
#include <bits/stdc++.h>
using namespace std;
int mod(int a, int m){
return (a % m + m) % m;
}
void solve(){
int n, m, q, op, i, x, k;
cin >> n >> m >> q;
vector<int> a(n+1);
for(int i=1; i<=n; i++)
cin >> a[i];
map<int, long long> ans;
for(int i=1; i*i<=m; i++)
if(!(m % i)){
ans[i] = 0;
ans[m/i] = 0;
}
for(pair<int, int> p : ans)
for(int i=1; i<=n; i++)
ans[p.first] += mod(a[i] - a[i-1], p.first);
while(q--){
cin >> op;
if(op == 1){
cin >> i >> x;
for(pair<int, int> p : ans){
ans[p.first] += mod(x - a[i-1], p.first) - mod(a[i] - a[i-1], p.first);
if(i != n)
ans[p.first] += mod(a[i+1] - x, p.first) - mod(a[i+1] - a[i], p.first);
}
a[i] = x;
}
else{
cin >> k;
cout << (ans[__gcd(k, m)] < m ? "YES" : "NO") << '\n';
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
int t;
cin >> t;
while(t--) solve();
}
Imagine putting all of the numbers from $$$0$$$ to $$$m-1$$$ in a grid, where each row is of size $$$\gcd(k, m)$$$. For example, if $$$k=8$$$ and $$$m=12$$$, our grid would look as follows:
| 8 | 9 | 10 | 11 |
| 4 | 5 | 6 | 7 |
| 0 | 1 | 2 | 3 |
Then observe that by applying operations, we can reach any element in the same column. Consider simulating the greedy process. Then we want to choose the lowest row possible; that is, we want to move up in the grid as infrequently as possible.
Notice that we only have to move up in the grid if $$$a_i \pmod{\gcd(k, m)} \lt a_{i-1} \pmod{\gcd(k, m)}$$$, because then we cannot stay in the same row. We want to move up in the grid $$$ \lt \frac{m}{\gcd(k, m)}$$$ times. So let's maintain the number of times we are forced to move up in the grid, for each $$$k$$$. This is quick to update, since when we update $$$a_i$$$, we only have to compare it to the two adjacent values.
Finally, we observe that $$$\gcd(k, m)$$$ is always a divisor of $$$m$$$, so we only have to maintain and update $$$d(m)$$$ different values. This allows us to answer queries in $$$O(d(m))$$$ time.
#include <bits/stdc++.h>
using namespace std;
void solve(){
int n, m, q, op, i, x, k;
cin >> n >> m >> q;
vector<int> a(n+1);
for(int i=1; i<=n; i++)
cin >> a[i];
map<int, int> ans;
for(int i=1; i*i<=m; i++)
if(!(m % i)){
ans[i] = 0;
ans[m/i] = 0;
}
for(pair<int, int> p : ans)
for(int i=1; i<=n; i++)
ans[p.first] += (a[i] % p.first < a[i-1] % p.first);
while(q--){
cin >> op;
if(op == 1){
cin >> i >> x;
for(pair<int, int> p : ans){
ans[p.first] += (x % p.first < a[i-1] % p.first) - (a[i] % p.first < a[i-1] % p.first);
if(i != n)
ans[p.first] += (a[i+1] % p.first < x % p.first) - (a[i+1] % p.first < a[i] % p.first);
}
a[i] = x;
}
else{
cin >> k;
cout << (ans[__gcd(k, m)] < m / __gcd(k, m) ? "YES" : "NO") << '\n';
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
int t;
cin >> t;
while(t--) solve();
}








Pen,Paperforces round
Bro dropped the editorial at the speed of light. Very refreshing contest btw!!
Fun fact: As a tester, testing for this contest was stopped once due to me.
Context for those who are curious: it turned out one of my problems was, up to a cosmetic rewording, a duplicate of a past ARC problem. beaten_by_ai luckily remembered the problem and it was removed.
https://atcoder.jp/contests/arc147/tasks/arc147_e
Initially, MEX Count was D (with a subtask to solve for one $$$k$$$) and Minimize Fixed Points was E, with the AtCoder problem placed at F. After it was removed, DE were moved to EF and Binary String Battle was added.
ahaa, thats why F is a bit easy i believe??
Note that the original problem is rated approx. $$$\color{orange}{2476}$$$, which roughly corresponds to $$$\color{red}{2585}$$$ in CodeForces. Therefore, we could have witnessed the hardest div3F in the history.
Thank you for the contest and the fast editorial!!!
assert(number_theory == magic);
editorial drops faster than brainrot memes hitting my youtube page
TUNG TUNG TUNG SAHUR TRALALERO TRALALA BOMBARDIRO CROCODILO TUNG TUNG TUNG TUNG TUNG
Am I the only one who got stuck on D and solved E? Very nice contest by the way, kudos
Opposite for me. It took me 7 minutes to solve D but I was stuck for more than an hour on E
It happened the same to me. I was able to do F kind of fast, but it took me much time to solve E
I got stuck on D and solved E and F
got stuck in D so bad that didn't got time to solve E :(
D was super wonky, E and F were easier imo
Same for me :)
D is one of those questions where you either solve it immediately or get stuck forever
problems were really interesting thank you for the great round!
This is the best div3 E i've ever seen
Perfectly balanced, as it should have been.
What could be the expected rating of the problems? ig A-B-C seems like a standard 900,1100, and 1200 rated. D was tricky but code is short so it can't be thought of more than 1400. E probably felt like 1500-1600. I don't know about F and G tho. What do you guys think?
A: 800 B: 800 C: 800 D: 1200 E: 1400 F: 1600 G: 2000
For A and B, I think they are ~800. C should be ~1000 (I think I got WA before AC because I had no idea what I was doing). D is really wonky and is not obvious, so I think it should be ~1300. E is not bad but requires a bit of work, so 1500~1600. F is straight-up divisor checking, so ~1600. G I didn't solve, so I just assume it's ~2000.
In D : Step 3 -> Take the example given after Bob gets s=00101111 Alice could convert this to s=00000010 and eventually win. I don't see how Bob wins this.
The strategy I see is Alice tries to make the array of the for 10001000/01000100 etc , and wherever Bob tries to reverse digits she flips back the ones Bob flips additionally being able to take care of extra ones. Hence, even if n>2k she can win.
What's wrong?
nevermind Bob would pick the newly found full 0 string , nice contest :)
Contest without graphs and dp after long time. Kudos to authors.
Clean editorial, easy to understand.
Although i was not able to solve F, it was a beautiful problem and worth spending my time on. Thank you for the contest
I solved F by calculating smallest prime factor of every number and then performing a greedy algorithm for prime numbers.
For me, E was way harder lmao (any hint for E?)
you can think of difference array technique to solve the problem. Also count of element only matters .
I was able to get E because i have done somewhat a similar question before. But here are some hints. I believe the editorial has a different solution to mine.
Try to figure out which MEX values are possible after removing k elements.
For each x, what is the minimum and maximum number of deletions that make it valid as MEX?
For each MEX candidate, find the deletion range [min_k, max_k] where it’s valid, then use sorting and binary search to count how many such ranges include each k from 0 to n.
You can do step 3 a bit differently to get O(N) total runtime. Take a look at my solution :)
Can you please share your solution , the contest is not reflecting in your profile
Here you go if anything is unclear feel free to ask
I understood the solution, Thanks for sharing :)
Great Contest, except D was horrible.
https://t.me/placementsoftware reirugan this is a telegram channel where answers were getting released during the contest, please check this and use it during the plagiarism check to ban the contestants who have used the exact same code in their submission.
don't worry this is being done
As always, please report cheaters on https://cf-cheater-database.vercel.app/.
can anyone please tell me how alice will win if n=5 k=3 and s = 11111
given: $$$11111$$$
alice: $$$01100$$$
bob: $$$01111$$$
alice: $$$00100$$$
bob: $$$00111$$$
alice: $$$00000$$$
great! This data also help me
can someone pls help me understand where I am going wrong in G? I am at a loss[submission:326909800]
https://codeforces.me/contest/2123/submission/326909800
just write high-low>=0 instead of high-low>0, otherwise you can break early in your binary search
Thanks a bunch dude the code got accepted.
Strange how all Problem A solutions match. Is this collective intelligence or something else?
I think it's just easy to guess. After checking n = 4 for instance, it's clear that the question has something to do with mod 4.
I did not get that remark , instead i thought that Alice choosing the smallest possible number is always optimal , ans it passed :) , my submission
G was good...
Can someone please explain D to me, especially step 3 in the editorial. I was able to come to the point where I observed that 1. If n is odd and the middle element is already 1 and rest count of 1 is at max k then its always possible for Alice to Win. 2. If n is even and middle 2 elements are 1 and rest count of 1 is at max k then again Alice can win. Basically I understood the reverse of step 2 that if I can force Bob to only be able to make a sequence of length exactly 'k' then Alice can win. Also k == half the length of string in above 2 cases.
But this condition, n < 2*k seems like magic to me.
Basically how to logically go from Step 2 -> Step 3 My Submission: https://codeforces.me/contest/2123/submission/326981142
you can think of it like this : in order for Alice to win , she needs at some point to make all the remaining ones included in all the substrings , so that whatever Bob does he can not get the full +k ones at his turn .And when we say included in all the substrings they must also be included in the first substring of length k . So we must ensure that when we divide the string into first (k) and last (n-k) elements , we should be sure that the ones in the first substring can be included in all other substrings , so (k) should be greater than (n-k) , reformulating : k>n-k --> 2*k>n is a necessary condition for Alice to win . hope it helps:)
Thanks, this idea that "all remaining ones must be present in all substrings" was the key idea I believe. I re-interpreted it in my own way. Basically, I need to ensure that in the worst case (odd length with 1 in the middle) too I am having a 'k' such that the first substring and last substring can cover it. This is only possible if they overlap, which means: length of first substring + length of last substring > n 2*k > n (since both are equal to 'k')
If my 'k' fulfills this condition then and count of 1`s > k then Alice always has a chance to win if she plays optimally.
Thanks a lot!! I am new and my maths is weak. How can I perform better on such problems?
Participate in virtual contests as much as you can !
I absolutely love the G problem. After reading the editorial, it just seems so obvious
Please help me to understand how the gcd property come here also how a % gcd(k,m) work in (a + k) % m ? Give me the proof please , actually i don't understand it.
bezout's lemma
the sol $$$O(tn^2)$$$ for prob A, 326827179
(What tf was I thinking?)
you are not alone on this lol , my submission
I was looking awoo 's Solution. for Problem E . I dont have any idea how this simple logic work, some. kind soul please help me. :
Think of it like marking the start and end of the increment, and the prefix sum “spreads” the value across the entire range. https://codeforces.me/blog/entry/78762
Btw, if you're asking about the full solution, try thinking about the problem in reverse: for each i, check whether it's possible to make the mex = i, and determine the minimum and maximum number of elements to remove to achieve that. (step 4 in this editorial)
ohh look what he is calulating for each possible mex he is calculating 2 values one is what is min number of element we need to remove to get ans as i and what is max number of value we ca remove get ans as i now for getting some value as min value is just its frequency and max value you can calculate first remove everyhting that is >= element . now when a mex is not possible we break now for each i we know we can get value as i for some k belongs to l to r then we just to linear sweeping between l to r incraesing value at l by +1 and value at r by +1 and doing prefix array sum
D was quite tricky, E,F were much easier
Great contest and balanced questions! Had that nostalgic codeforces feel many contests these days don't
can anyone please explain why does my code exceed time limit in testcase 30 (326998284)
I'm using an array for count which should be better than a map as provided in the solution
Sum of m isn't bound by anything
my bad, I defined cnt twice one with size MAX and one with m + 1
Alternative solution to F:
Don't even have to check primes for F. Just cycle each odd number with all its multiples that haven't been filled yet. And then cycle all leftover even numbers. If p is a prime number, then 2 * p won't be filled by any odd number, except p, because 2 * p is only divisible by p and 2. This is my solution to F btw.
https://codeforces.me/contest/2123/submission/327001514
very cool
I think my solution F is shorter:
https://codeforces.me/contest/2123/submission/326908482
Anybody body know what is wrong with this? https://codeforces.me/contest/2123/submission/326994630, stops on test 13?
Can someone help me find why my greedy approach is wrong for d . Basically i am greedily converting the outermost k 1's of the string to 0 , and then checking if i can get a substring of length k+1 . Here's my submission — 326923441
my idea was that if bob can make k+1 consecutive 1 then he always win
Your approach is incorrect. Consider the following example:
n = 5, k = 3 s = "11111"
After Alice's first move—if she plays optimally—the string will become "01010". Now, Bob is left with a maximum substring of consecutive zeroes of length 1, so he can turn at most 3 characters into '1'. On her next move, Alice can easily turn all the characters back to '0'.
i had pretty simple approach on F!!....
https://codeforces.me/contest/2123/submission/326973038
I just swap x with its largest divisor!
I only came up with C with 1 minute left xD Don't know when am I finally touching Ds
Did you read your comment before commenting?
now that you mention it...
Am I the only one, who solved problem E using Merge Sort Tree? Because when you realise, that 0 <= i <= min(n-k, mex) and freq(i) <= k it turns out to be a straightforward Merge Sort Tree task (and I couldn't figure out a different solution)
For question F , I just iterated from n to 1
and swapped it with the max divisor
Writing Solutions step wise is even more confusing . BEA!
Editorial of G seems too much complicated to understand ? Is anyone able to make it more simpler ?
I tried chat GPT.
It helped.
Any way, I am getting WA but can't tell whats wrong in my code
327149170
Can some one lend some brain power?
Thanks
Found one silly mistake
Now on TLE on test 23 327273197
After removing all binary data structures, and using global data stores
Now i achieved TLE on test 29 327276612
reirugan is there any special reason why input constrain are so tight?
My way to calculate divisors was innefficient, still normal code with STL's binary structure based data type like map, vector::push_back() gave TLE :)
I had to re write code to optimize time with so many unconventional ways. this seem so unnecessary it also waist lot of compute resources of codeforces engines.
I think five seconds is pretty lenient? Some solutions ran as fast as 312ms.
My fully optimized code ran in 1200ms
beyond this I can only think about rewriting input reader myself. and precomputing gcd? (not sure if that is possible)
Thanks for lovely problem though, enjoyed every bit brain fuck, and connecting dots to understand solution.
saw one of those solution they optimized by scaling down possible divisors , by only focusing on divisors based on query input.
True, but even the solution codes in the editorial both run in around 2.5 seconds, and they are rather unoptimized (using map, for example). I think it's fair to set the time limit to double that.
Key observation is
$$$(a + (k.n))\mod{m}$$$ where $$$n\in{N}$$$, can be written as $$$a\mod{gcd(k,m)}$$$
possible values you can transform $$$a_i$$$ for given any $$$k$$$ is congruent to $$$a_i\mod{gcd(k,m)}$$$
for any value of $$$k$$$, $$$gcd(k,m)$$$ will be a divisor of $$$m$$$ which means there are only less than $$$800$$$ values possible for divisors (given $$$m \lt 5\times{1e5}$$$)
For each divisor you can keep array $$$a$$$ transformed into $$$a_i\mod{d|m}$$$
you can keep precomputed sum of all arrays (arrays based on divisor of m). and determine answer.
Question G — Could someone please explain why ai(mod(gcd(k, m)) is the invariant across the operations? Where did gcd(k, m) come from?
Let x=gcd(k,m). Since x divides k, adding k keeps ai invariant mod x because k is congruent to 0 mod x. Similarly, taking ai modulo m keeps ai invariant modulo x because x divides m.
So for all common divisors 'c' of k and m, ai must be invariant mod c.. right? Then why did we use gcd only?
Because using anything less than gcd means that you will have to use the operation more times than if you used gcd, which leads to WA
Where did gcd(k, m) come from?
I like to imagine in term of grid, picture m=10, k-5, ai=3
keep doing ai + k for few times and you get
now see how would (ai + k) mod m would look, by wrapping this list every 10 chars
You can see ai + k only ever return in 2 possible values, if you look at these values mod gcd(10,5), i.e. mod 5
you can see ai mod (gcd(k,m)) is invariant. that means you can only set ai to ai mod (gcd(k,m)) being smallest possible value and take gcd(k,m) steps at a time.
if gcd(k, m) is 1 you can make ai any value, try to picture same with k = 7.
why gcd(k, m) in problem G?
This should be the gold standard for editorial quality. Feedback for problem quality and difficulty and the solutions explained in collapsible steps. I also really liked the tester rating predictions. I don't expect all editorials to be of this quality, but I certainly appreciate it!
We can optimize the solution for problem E using a difference array. Let cnt[x] be the frequency of value x. For x < mex, it contributes to answer k iff cnt[x] ≤ k ≤ n − x − 1.
Each x defines a valid interval on k. We add +1 on [cnt[x], n − x − 1] using a difference array, then take prefix sums.
This avoids sets/maps and runs in O(n) time with O(n) memory instead of O(nlogn) time complexity.
Solution for Problem C — Prefix Min and Suffix Max:
Intuition: If an array element is either the minimum element of its prefix or the maximum element of its suffix (or both), then we can reduce the whole array down to that single element using the given operations. Otherwise, we can't. For example, let's say the array looks like this:
a = [13, 10, 12, 20]
Let's look at a couple of example elements in this array. First, let's define a[i..j] to be the contiguous subarray from index i to j inclusive.
For the third element, a[2] = 12, its prefix is a[0..2] = [13, 10, 12] and its suffix is a[2..3] = [12, 20], so it is neither the min of its prefix or the max of its suffix, so we output 0 for this element.
For the first element, a[0] = 13, its prefix is a[0..0] = [13] and its suffix is a[0..3] = [13, 10, 12, 20], and it is the min of its prefix. So we output 1 for this element.
Why does this idea work? Let's look at the case where an element is the minimum of its prefix first:
Theorem 1: If an element x is the minimum of its prefix, then we can reduce the array down to x.
Proof: Let's suppose we have any array a. Also, assume that a[i] = x and it is the min of its prefix a[0..i]. Then we can use the prefix operation to replace this prefix by x. After this there two possible cases:
One can make a similar argument to the above when an element is the the maximum of its suffix.
The only remaining thing we need to prove is that if an element is neither the minimum of its prefix nor the maximum of its suffix, then we cannot reduce the array to that single element:
Theorem 2: If an element x is neither the minimum of its prefix nor the maximum of its suffix, then we cannot reduce the array down to x.
Proof: Suppose we have an array a and an element a[i] = x in the array which is neither the minimum of its prefix nor the maximum of its suffix. Then x cannot be the first or the last element in the array (why?). So we have an array that looks like this:
a = [..z..x..y..]
where z is the minimum of the prefix of x and y is the maximum of the suffix of x. Here the ".." just means any other remaining elements (possibly zero).
We can show that we cannot reduce the array a down to the element x by itself:
Suppose start with some operation. This operation cannot include the element x because then we would eliminate x. If it is a prefix operation it cannot eliminate z. If it is a suffix operation it cannot eliminate y (why?).
So after the first operation z is still to the left of x and y is still to the right of x. Now we can repeat the same argument for any operation following the first one.
But eventually we must include x in some operation, otherwise we cannot reduce the array a down to just x. But if we do this, we will eliminate x since if it's a prefix operation it will include z and x (in which case x will be eliminated since z < x), and if it's a suffix operation it will include y and x (because y > x).
So we get a contradiction because in order to reduce the array down to x by itself, we must eventually include x in some operation, but if we do this we must eliminate x.
Implementation:
Below is the implementation of the solution in Java. The printSolution function contains the main algorithm for the problem. For the implementation we do two scans: One from left to right to check whether each element is the minimum of its prefix, and one from right to left to check whether each element is a the maximum of its suffix. During the second scan we check for each element whether it is a min of its prefix or max of its suffix and output the solution value for that element accordingly.
For Question F, can we say that the minimum number of fixed points in such a permutation is the number of prime numbers greater than n/2 + 1(This one comes from the number 1 itself)