Codeforces Round 1048 (Div. 1, Div. 2) Editorial
Difference between en28 and en29, changed 0 character(s)
[2139A — Maple and Multiplication](https://mirror.codeforces.com/contest/2139/problem/A)↵

Idea: [user:installb,2025-09-08]↵
Preparation: [user:installb,2025-09-08],[user:2014CAIS01,2025-09-08]↵

<spoiler summary="Solution">↵

If $a=b$ we need $0$ steps.↵

If $a$ can be divided by $b$, we only need $1$ step, which is to multiply $b$ by $\frac{a}{b}$.  Same for the case when $b$ can be divided by $a$.↵

Otherwise, we need at most $2$ steps. As both $a$ and $b$ are positive integers, we can first multiply $a$ by $b$ and then multiply $b$ by the original value of $a$. Both number will be equal to $a\times b$.↵

</spoiler>↵

<spoiler summary="Code (C++)">↵

```cpp↵
#include <bits/stdc++.h>↵
using namespace std;↵
typedef long long ll;↵
 ↵
int solve(){↵
    int a,b;↵
    cin >> a >> b;↵
    if(a == b) return 0;↵
    if(a % b == 0 || b % a == 0) return 1;↵
    return 2;↵
}↵
 ↵
int main(){↵
    ios::sync_with_stdio(false);↵
    int TC;↵
    cin >> TC;↵
    while(TC --){↵
        cout << solve() << '\n';↵
    }↵
    return 0;↵
}↵
```↵

</spoiler>↵

<spoiler summary="Rate this problem">↵

- Amazing problem: [likes:1]↵
- Good problem: [likes:2]↵
- Average problem: [likes:3]↵
- Bad problem: [likes:4]↵
- Horrible problem: [likes:5]↵

</spoiler>↵

[2139B &mdash; Cake Collection](https://mirror.codeforces.com/contest/2139/problem/B)↵

Idea: [user:installb,2025-09-08]↵
Preparation: [user:installb,2025-09-08]↵

<spoiler summary="Solution">↵

The number of cakes collected from an oven depends only on the last time Maple visits it. Therefore, in the optimal strategy, she should visit distinct ovens in the last $\min(m,n)$ seconds.↵

Let's think in reverse: suppose we fix an order $p_1,\dots,p_n$ of the ovens. Then at second $m$ we visit oven $p_1$, at second $m-1$ we visit oven $p_2$, and so on. For the $i$-th oven in this order, we collect $a_{p_i}\cdot \max(0, m-i+1)$ cakes.↵

To maximize the total number of cakes collected, ovens with larger $a_i$ should be visited later (i.e., assigned larger multipliers). Thus we sort $a$ in non-increasing order first.↵

The final answer is $\sum_{i=1}^n a_i \cdot \max(0, m-i+1)$.↵

</spoiler>↵

<spoiler summary="Code (C++)">↵

```cpp↵
#include <bits/stdc++.h>↵
using namespace std;↵
typedef long long ll;↵
const int INF = 0x3f3f3f3f;↵
 ↵
void solve(){↵
    int n,t;↵
    cin >> n >> t;↵
    ll ans = 0;↵
    vector <int> a(n);↵
    for(int i = 0;i < n;i ++) cin >> a[i];↵
    sort(a.begin(),a.begin() + n,greater <int>());↵
    for(int i = 0;i < n;i ++) ans += 1ll * a[i] * max(0,t - i);↵
    cout << ans << '\n';↵
}↵
 ↵
int main(){↵
    ios::sync_with_stdio(false);↵
    int TC;↵
    cin >> TC;↵
    while(TC --){↵
        solve();↵
    }↵
    return 0;↵
}↵
```↵

</spoiler>↵

<spoiler summary="Rate this problem">↵

- Amazing problem: [likes:6]↵
- Good problem: [likes:7]↵
- Average problem: [likes:8]↵
- Bad problem: [likes:9]↵
- Horrible problem: [likes:10]↵

</spoiler>↵

[2138A &mdash; Cake Assignment](https://mirror.codeforces.com/contest/2138/problem/A)↵

Idea: [user:wjy666,2025-09-08]↵
Preparation: [user:wjy666,2025-09-08]↵

<spoiler summary="Hint">↵

You can backtrack from the final state.↵

</spoiler>↵

<spoiler summary="Solution">↵

Denote the state $(a,b)$ that indicates Chocola has $a$ cakes and Vanilla has $b$ cakes.↵

After one operation of type $1$, Vanilla's number of cakes will definitely be at least half of the total, and similarly for operation $2$.↵
If $0 < a < 2^{k}$, then $2^{k} < b < 2^{k+1}$, meaning the previous operation must have been type $1$. Similarly, if $0 < b < 2^{k}$, the previous operation must have been type $2$.↵

Therefore, you can backtrack from the final state $(x,2^{k+1}-x)$, until it reaches the initial state $(2^k,2^k)$.↵

Now let's analyze how many steps we need to do during the process.↵

For the state $(a, b)$, where $a, b \neq 0$, assume $a = i \cdot 2^{p_a}$ and $b = j \cdot 2^{p_b}$, $i$ and $j$ are positive odd integers.↵

Since $a + b = 2^{k+1}$, it must be true that $ 0 \le p_a = p_b \le k$ , and after one operation $1$ or $2$, both $p_a$ and $p_b$ decrease by exactly $1$.↵

Therefore, the whole process takes at most $k$ steps, so we solve the problem with $O(tk)$ time complexity.↵

</spoiler>↵

<spoiler summary="Code (C++)">↵

```cpp↵
#include <bits/stdc++.h> ↵
using namespace std;↵
int main(){↵
    int t; cin>>t;↵
    while(t--){↵
        long long k,x,kk; cin>>k>>x; kk=1ll<<k;↵
        if (!x||x==kk*2) {cout<<"-1\n"; continue;}↵
        long long y=kk*2-x;↵
        vector<int> ans; ans.clear();↵
        while(x!=kk){↵
            if (x>y) ans.push_back(2),x-=y,y*=2;↵
            else ans.push_back(1),y-=x,x*=2;↵
        }↵
        cout<<ans.size()<<"\n";↵
        while(!ans.empty()) cout<<ans.back()<<' ',ans.pop_back();↵
        cout<<"\n";↵
    }↵
    return 0;↵
}↵
```↵

</spoiler>↵

<spoiler summary="Rate this problem">↵

- Amazing problem: [likes:11]↵
- Good problem: [likes:12]↵
- Average problem: [likes:13]↵
- Bad problem: [likes:14]↵
- Horrible problem: [likes:15]↵

</spoiler>↵

[2138B &mdash; Antiamuny Wants to Learn Swap](https://mirror.codeforces.com/contest/2138/problem/B)↵

Idea: [user:tarjen,2025-09-08]↵
Preparation: [user:installb,2025-09-08],[user:tarjen,2025-09-08],[user:2014CAIS01,2025-09-08]↵

<spoiler summary="Solution">↵

For array $b$, we can prove that $f(b)\neq g(b)$ **if and only if** there exists indexes $1\le i<j<k\le m$ which satisfies $b_i>b_j>b_k$.↵

Since $a$ is a permutation, all elements in $b$ should be distinct. $g(b)$ is equal to the number of inversions in $b$. When there exists some index $i$ that satisfies $a_i>a_{i+1}>a_{i+2}$, we can reduce the number of inversions by $3$ by applying operation $2$, allowing $f(b)$ to become less than $g(b)$. This is the only case where you can reduce more than $1$ inversion with one operation.↵

If there exists indexes $1\le i<j<k\le m$ which satisfies $b_i>b_j>b_k$. We can first choose index $i,k$, then move all elements greater than $b_i$ to the right of $b_k$ and move all elements less than $b_k$ to the left of $b_i$ by swapping adjacent numbers (applying the first operation). Now all elements $b_p$ between $b_i,b_k$ satisfy $b_i>b_p>b_k$. We then swap them to the left of $b_i$ until there is only one element $b_j$ left. Now $b_i>b_j>b_k$ and they are adjacent, and we can apply operation $2$ on the current index of $b_i$.↵

If we only apply operation 1 on indexes $i$ which satisfy $b_i>b_{i+1}$, there will never exist any index $i$ satisfying $b_i>b_{i+1}>b_{i+2}$ in $b$ during the process. If we apply an operation $1$ on some index $i$ where $b_i<b_{i+1}$, the number of inversions will be increased by $1$ instead of decreased by $1$, which makes it impossible to reach $f(b)<g(b)$ with one operation $2$, even i it decreases number of inversions by $3$. Therefore, in this case $f(b)=g(b)$.↵

For each element $a_i$, we define:↵

- $l_i$: the maximum index $< i$ such that $a_{l_i} > a_i$,↵
- $r_i$: the minimum index $> i$ such that $a_{r_i} < a_i$.↵

Then the answer to a query $[l, r]$ is $\texttt{NO}$ if and only if some segment $[l_i, r_i]$ lies fully inside $[l, r]$.↵

To answer multiple queries, you can preprocess the smallest $r$ for every $l$ such that the answers for all $[l,x](x\ge r)$ should be $\texttt{NO}$.↵

The time complexity is $O(n)$ if you find $l_i,r_i$ with the Monotonic Stack trick. $O(n\log n)$ solutions can also pass.↵

</spoiler>↵

<spoiler summary="Code (C++)">↵

```cpp↵
#include <bits/stdc++.h>↵
using namespace std;↵
void solve()↵
{↵
    int n, q;↵
    cin >> n >> q;↵
    vector<int> a(n + 2);↵
    for (int i = 1; i <= n; i++)↵
    {↵
        cin >> a[i];↵
    }↵
 ↵
    vector<int> mxl(n + 1), mir(n + 1);↵
    for (int i = 1; i <= n; i++)↵
    {↵
        mxl[i] = i - 1;↵
        while (mxl[i] > 0 && a[mxl[i]] < a[i])↵
            mxl[i] = mxl[mxl[i]];↵
    }↵
    for (int i = n; i >= 1; i--)↵
    {↵
        mir[i] = i + 1;↵
        while (mir[i] <= n && a[mir[i]] > a[i])↵
            mir[i] = mir[mir[i]];↵
    }↵
    vector<int> L(n + 1, 0);↵
    for (int i = 2; i < n; i++)↵
    {↵
        if (mxl[i] > 0 && mir[i] <= n)↵
        {↵
            L[mir[i]] = max(L[mir[i]], mxl[i]);↵
        }↵
    }↵
    for (int i = 1; i <= n; i++)↵
    {↵
        L[i] = max(L[i], L[i - 1]);↵
    }↵
 ↵
    for (int i = 0; i < q; i++)↵
    {↵
        int l, r;↵
        cin >> l >> r;↵
        if (l <= L[r])↵
            cout << "NO\n";↵
        else↵
            cout << "YES\n";↵
    }↵
}↵
int main()↵
{↵
    ios::sync_with_stdio(false);↵
    cin.tie(0);↵
    int T;↵
    cin >> T;↵
    while (T--)↵
    {↵
        solve();↵
    }↵
}↵
```↵

</spoiler>↵

<spoiler summary="Rate this problem">↵

- Amazing problem: [likes:16]↵
- Good problem: [likes:17]↵
- Average problem: [likes:18]↵
- Bad problem: [likes:19]↵
- Horrible problem: [likes:20]↵

</spoiler>↵

[2138C1 &mdash; Maple and Tree Beauty (Easy Version)](https://mirror.codeforces.com/contest/2138/problem/C1)↵

Idea: [user:installb,2025-09-08]↵
Preparation: [user:installb,2025-09-08],[user:tarjen,2025-09-08],[user:2014CAIS01,2025-09-08]↵

<spoiler summary="Solution">↵

We can first find out that the maximum possible answer is the minimum depth among all leaves $d=\min\{dep_u\}$, as the LCS can't be greater than the minimum length of all names.↵

We consider a special case first where all leaves have the same depth. If we want to achieve the maximum answer $d$, the names of all leaves should be exactly the same. Which means, for any two vertices with the same depth, their label has to be the same.↵

For each depth $i$, we group all vertices with depth $i$ together as the $i$-th group (suppose root has depth $1$). For each group, all vertices in the group should have the same label. Let the size of groups $1,\cdots,d$ be $c_1,\cdots,c_d$. Now the problem can be considered as a knapsack problem, where you have $d$ items with weight $c_1,\cdots,c_d$. We need to find out whether you can take several numbers from $c$ that have sum equal to $k$. This can be solved in $O(n^2)$.↵

If the maximum answer $d$ is not achievable, we can show that you can always achieve $w-1$. From for each group from the first to the $d$-th, we assgin an arbitrary label which still have at least $c_i$ numbers remaining to all vertices in the group. As all leaves have the same depth, $c_d$ should be the maximum element in the array, so you are always able to select a label for groups $1$ to $d-1$. Then arbitrarily distribute the remaining labels among vertices in the last groups (which are leaves)..↵

Now consider the general case where not all leaves have the same depth. If we want to achieve answer $=d$, we need to select $d$ groups. For each leaf vertex $v$, there should exist a vertex in the $d$-th group which is an ancestor of $v$. And for every $2\le i\le d$, for each vertex $v$ in the $i$-th group, there should exist a vertex in the $i-1$-th group which is an ancestor of $v$. All vertices in the same group should have the same label. Suppose the $i$-th group has label $l_i$, then we can achieve $\text{LCS}=l_1l_2\ldots l_d$ which has length $d$.↵

We can still group all vertices with depth $1\le i\le d$ together as the $i$-th group. For all vertices with depth $>d$, we can set their label arbitrarily. We can view them as items with weight $1$ in the knapsack problem.↵

And we can show this is the optimal way to select $d$ groups. If some vertex $u$ with depth $\le d$ is not selected, there must be some vertices selected in some group in the subtree of $u$, because the path from root to $u$ consists of less than $d$ vertices. If the smallest group index that some vertex in the subtree of $u$ belongs to is $i$, we can instead let $u$ be inside the $i$-th group, and then the labels of all vertices in the subtree $u$ that were previously in group $i$ can be selected arbitrarily. If we consider the knapsack problem, we have reduced some $c_i$ by $x$ and added $x$ items with weight $1$. All achievable values still remain achievable, while some previously unachievable values become achievable.↵

The time complexity is $O(n^2)$, the bottleneck is knapsack.↵

</spoiler>↵

<spoiler summary="Code (C++)">↵

```cpp↵
// n^2/w↵
#include <bits/stdc++.h>↵
using namespace std;↵
int solve() {↵
    int n, k;↵
    cin >> n >> k;↵
    vector<int> fa(n, -1), dep(n, 0);↵
    vector<int> noson(n, 1), cnt(n + 1);↵
    cnt[0]++;↵
    for (int i = 1; i < n; i++) {↵
        cin >> fa[i], fa[i]--;↵
        dep[i] = dep[fa[i]] + 1;↵
        cnt[dep[i]]++;↵
        noson[fa[i]] = 0;↵
    }↵
    int mxdep = 1e9;↵
    for (int i = 0; i < n; i++)↵
        if (noson[i]) mxdep = min(mxdep, dep[i]);↵
 ↵
    int sum = 0;↵
 ↵
    vector<int> dp(n + 1);↵
    dp[0] = 1;↵
    for (int i = 0; i <= mxdep; i++) {↵
        for (int j = sum; j >= 0; j--) dp[j + cnt[i]] |= dp[j];↵
        sum += cnt[i];↵
    }↵
    if (sum <= k || sum <= n - k) return mxdep + 1;↵
    for (int i = 0; i <= sum; i++)↵
        if (dp[i]) {↵
            if (i <= k && sum - i <= n - k) return mxdep + 1;↵
        }↵
    return mxdep;↵
}↵
int main() {↵
    ios::sync_with_stdio(false);↵
    cin.tie(0);↵
    int T;↵
    cin >> T;↵
    while (T--) cout << solve() << "\n";↵
    return 0;↵
}↵
```↵

</spoiler>↵

<spoiler summary="Rate this problem">↵

- Amazing problem: [likes:26]↵
- Good problem: [likes:27]↵
- Average problem: [likes:28]↵
- Bad problem: [likes:29]↵
- Horrible problem: [likes:30]↵

</spoiler>↵

[2138C2 &mdash; Maple and Tree Beauty (Hard Version)](https://mirror.codeforces.com/contest/2138/problem/C2)↵

Idea: [user:installb,2025-09-08]↵
Preparation: [user:installb,2025-09-08],[user:tarjen,2025-09-08],[user:2014CAIS01,2025-09-08]↵

<spoiler summary="Solution">↵

We focus on optimizing the knapsack problem. In the knapsack problem we only need to know $f_i=0/1$ which means whether you can achieve sum $i$, so we can optimize the knapsack with bitset. The time complexity is $O(\frac{n^2}{\omega})$ which is enough to pass E2.↵

But actually we can do better. For the knapsack problem, it has at most $n$ items, and the sum of weights of all items is also at most $n$. We can do a sqrt decomposition trick here. ↵

- For items with weight $\ge\sqrt{n}$, there are at most $\sqrt{n}$ such items.↵
- For items with weight $<\sqrt{n}$, we count the number of items for each different weight. If there are $c_w$ items for weight $w$, we decompose $x$ into $c_w=2^0+2^1+\cdots+2^k+y$ where $k$ is the largest integer satisfying $2^0+2^1+\ldots+2^k\le c_w$. Then we create new items new items with weights $2^0\cdot w,2^1\cdot w,\ldots,2^k\cdot w,y\cdot w$. The set of new items is same as $c_w$ items with weight $w$ if we only consider the different sum of weights the set of items can achieve. Now we only have $\sum_{w=1}^{\sqrt{n}}\log(c_w)=\sqrt{n}$ items.↵

The total time complexity is $O(\sqrt{n}\cdot n+\sqrt{n}\cdot n)=O(n\sqrt{n})$.↵

And this can also be optimized with bitset, leading to an $O(\frac{n\sqrt{n}}{\omega})$ solution.↵

</spoiler>↵


<spoiler summary="Code (C++)">↵

```cpp↵
// nsqrtn/w↵
#include <bits/stdc++.h>↵
using namespace std;↵
const int N = 2e5 + 10;↵
template <int maxn>↵
int solve(int n, int k) {↵
    if (maxn <= n) {↵
        return solve<min(N, maxn * 2)>(n, k);↵
    }↵
    bitset<maxn> dp;↵
    vector<int> fa(n, -1), dep(n, 0);↵
    vector<int> noson(n, 1), cnt(n + 1);↵
    cnt[0]++;↵
    for (int i = 1; i < n; i++) {↵
        cin >> fa[i], fa[i]--;↵
        dep[i] = dep[fa[i]] + 1;↵
        cnt[dep[i]]++;↵
        noson[fa[i]] = 0;↵
    }↵
    dp.reset();↵
    dp[0] = 1;↵
    int mxdep = 1e9;↵
    for (int i = 0; i < n; i++)↵
        if (noson[i]) mxdep = min(mxdep, dep[i]);↵
 ↵
    int sum = 0;↵
    vector<int> all(cnt.begin(), cnt.begin() + mxdep + 1);↵
    sort(all.begin(), all.end());↵
    vector<int> v;↵
    for (int i = 0; i < (int)all.size(); i++) {↵
        int j = i;↵
        while (j + 1 < (int)all.size() && all[i] == all[j + 1]) j++;↵
        int t = j - i + 1;↵
        for (int z = 1; z <= t; z *= 2) {↵
            v.push_back(z * all[i]);↵
            t -= z;↵
        }↵
        if (t > 0) v.push_back(t * all[i]);↵
        i = j;↵
    }↵
    dp[0] = 1;↵
    for (auto val : v) {↵
        sum += val;↵
        dp |= (dp << val);↵
    }↵
    if (sum <= k || sum <= n - k) return mxdep + 1;↵
    for (int i = 0; i <= sum; i++)↵
        if (dp[i]) {↵
            if (i <= k && sum - i <= n - k) return mxdep + 1;↵
        }↵
    return mxdep;↵
}↵
int main() {↵
    ios::sync_with_stdio(false);↵
    cin.tie(0);↵
    int T;↵
    cin >> T;↵
    while (T--) {↵
        int n, k;↵
        cin >> n >> k;↵
        cout << solve<1>(n, k) << "\n";↵
    }↵
    return 0;↵
}↵
```↵

</spoiler>↵

<spoiler summary="Rate this problem">↵

- Amazing problem: [likes:21]↵
- Good problem: [likes:22]↵
- Average problem: [likes:23]↵
- Bad problem: [likes:24]↵
- Horrible problem: [likes:25]↵

</spoiler>↵

[2139D &mdash; Antiamuny and Slider Movement](https://mirror.codeforces.com/contest/2138/problem/D)↵

Idea: [user:tarjen,2025-09-08],[user:Starsilk,2025-09-08]↵
Preparation: [user:installb,2025-09-08],[user:tarjen,2025-09-08],[user:Starsilk,2025-09-08]↵

<spoiler summary="Solution">↵

Let’s define $b_i$ as the position of the $i$-th slider decreased by $i$. Every operation on the sliders can be interpreted as a modification of the array $b$.↵

- If we increase the position of slider $i$, then $b_i$ increases. At the same time, every suffix element $b_{i+1}, b_{i+2}, \dots, b_n$ gets updated to $b_j := \max(b_j, b_i)$.↵
  ↵
- If we decrease the position of slider $i$, then $b_i$ decreases. At the same time, every prefix element $b_1, b_2, \dots, b_{i-1}$ gets updated to $b_j := \min(b_j, b_i)$.↵

Since the array $b$ always remains **non-decreasing**, we can reinterpret operations as follows:↵

- Every operation simultaneously applies a $\min$ operation to all elements on the left, and a $\max$ operation to all elements on the right.↵

For a fixed slider $b_i$, the effect of each operation on the slider should be one of the following:↵

1. $b_i := \max(b_i, x)$↵
2. $b_i := \min(b_i, x)$↵
3. $b_i := x$ (assignment)↵

Our task is to compute the sum of final values of $b_i$ after all possible sequences of operations.↵

We sort all operations by their parameter $x$. If multiple operations share the same $x$, we give them a consistent order and then assume all $x$ are distinct in the following part of the editorial.↵

We first suppose that the position of the slider is changed at least once. Suppose the final value for slider $i$ is $b_e$, let’s consider which operation sets $b_i = b_e$ at the very end.↵

At this point, we no longer care about the exact value of $b_i$ during the process — only whether it is less than, equal to, or greater than $b_e$.↵

All operations of type $\max$ with $x < b_e$ and type $\min$ with $x > b_e$ are irrelevant. We can insert them anywhere after deciding the order of other operations without affecting the result. We won't consider these operations in the following parts of the editorial.↵

All assignment operations $b_i := x$ can be reinterpreted:↵

- If $x < b_e$, treat it as $b_i := \min(b_i, x)$.↵
- If $x > b_e$, treat it as $b_i := \max(b_i, x)$.↵

The last operation, that makes $b_i = b_e$ must be the one with parameter $x = b_e$.↵

- If this operation is assignment, then all other operations can appear in any order.↵

- If this operation is $\max$ type, then immediately before it we must have $b_i < b_e$.↵
- - Either the last preceding valid operation is some $\min$ type operation making $b_i < b_e$;↵
- - Or no other effective operation occurs, and the initial value of $b_i$ was already smaller than $b_e$.↵

- If this operation is $\min$ type operation, it is symmetric: either the last preceding valid operation is a $\max$ type operation, or the initial value of $b_i$ was already larger than $b_e$.↵

Finally, don’t forget the case where a slider is never touched, where it simply keeps its initial value.↵

For each of the $n$ sliders, we need to check contributions over all $m$ operations. The overall time complexity is $O(nm)$.↵

</spoiler>↵

<spoiler summary="Code (C++)">↵

```cpp↵
#include<bits/stdc++.h>↵
using namespace std;↵
const long long mod=1000000007;↵
long long a[5000],ans[5000],tt[5001],inv[5001];↵
struct apos{↵
long long id;↵
long long x;↵
friend bool operator<(apos a,apos b){↵
return a.x<b.x;↵
}↵
}ap[5000];↵
int main(){↵
ios::sync_with_stdio(false),cin.tie(0);↵
int T,flag;↵
long long n,m,p,q,x,i,j,cl,cr;↵
tt[0]=1;↵
for(i=1;i<=5000;i++)tt[i]=tt[i-1]*i%mod;↵
inv[1]=1;↵
for(i=2;i<=5000;i++)inv[i]=(mod-mod/i)*inv[mod%i]%mod;↵
for(cin>>T;T>0;T--)↵
{↵
cin>>n>>m>>p;↵
for(i=0;i<n;i++)↵
{↵
cin>>a[i];↵
a[i]-=i;↵
}↵
for(i=0;i<p;i++)↵
{↵
cin>>ap[i].id>>ap[i].x;↵
ap[i].id--;↵
ap[i].x-=ap[i].id;↵
}↵
sort(ap,ap+p);↵
for(i=0;i<n;i++)↵
{↵
flag=0;↵
for(j=0;j<p;j++)↵
{↵
if(ap[j].id<=i&&ap[j].x>=a[i])flag=1;↵
if(ap[j].id>=i&&ap[j].x<a[i])flag=1;↵
}↵
if(!flag)↵
{↵
ans[i]=a[i]+i;↵
continue;↵
}↵
ans[i]=0;↵
cl=0;↵
cr=0;↵
for(j=0;j<p;j++)↵
{↵
if(ap[j].id<=i)cr++;↵
}↵
for(j=0;j<p;j++)↵
{↵
if(ap[j].id<=i)cr--;↵
if(ap[j].id==i)ans[i]=(ans[i]+(ap[j].x+i)*inv[cl+cr+1])%mod;↵
if(ap[j].id<i)↵
{↵
if(cl==0&&cr==0&&a[i]<=ap[j].x)ans[i]=(ans[i]+ap[j].x+i)%mod;↵
else ans[i]=(ans[i]+(ap[j].x+i)*inv[cl+cr+1]%mod*inv[cl+cr]%mod*cl)%mod;↵
}↵
if(ap[j].id>i)↵
{↵
if(cl==0&&cr==0&&a[i]>ap[j].x)ans[i]=(ans[i]+ap[j].x+i)%mod;↵
else ans[i]=(ans[i]+(ap[j].x+i)*inv[cl+cr+1]%mod*inv[cl+cr]%mod*cr)%mod;↵
}↵
if(ap[j].id>=i)cl++;↵
}↵
}↵
for(int x = 0;x < n;x ++)↵
{↵
cout<<ans[x]*tt[p]%mod<<' ';↵
}↵
cout<<'\n';↵
}↵
return 0;↵
}↵
```↵

</spoiler>↵

<spoiler summary="Rate this problem">↵

- Amazing problem: [likes:31]↵
- Good problem: [likes:32]↵
- Average problem: [likes:33]↵
- Bad problem: [likes:34]↵
- Horrible problem: [likes:35]↵

</spoiler>↵

[2139E1 &mdash; Determinant Construction (Easy Version)](https://mirror.codeforces.com/contest/2138/problem/E1)↵

Idea: [user:wjy666,2025-09-08]↵
Preparation: [user:wjy666,2025-09-08]↵

<spoiler summary="Solution 1">↵

Thanks to [user:jqdai0815,2025-09-08] for his significant contribution to this solution.↵

<spoiler summary="Step 1">↵

We can consider transforming the construction of a matrix into the construction of a directed graph, as the determinant and permutations are closely related to the cycle covers of a directed graph.↵

If we have a directed graph with $n$ vertices, a cycle cover is a set of $n$ edges such that each vertex has exactly one incoming edge and one outgoing edge in this set (self-loops are allowed). In other words, these $n$ edges form one or more cycles that together cover all vertices in the graph.↵

In a complete directed graph (with self-loops), every permutation of the vertices determines a cycle cover and vice versa. (The cycles of the permutation are precisely the cycles in the cover.)↵

We consider the definition of the determinant:↵

$$↵
\det(M)=\sum_{\begin{subarray}{c}B=(b_{0},\ldots,b_{n-1})\\ B\in\mathcal{P}_{n}\end{subarray}}(-1)^{\mathrm{inv}(B)}\cdot\prod_{i=0}^{n-1}m_ {i,b_{i}}↵
$$↵

This summation goes over all permutations $B$, in other words, over all cycle covers of the directed graph determined by the adjacency matrix $M$. We can also interpret $m_{i,j}=0$ as "the edge from $i$ to $j$ does not exist at all". Thus, the product term $\prod_{i=0}^{n-1}m_ {i,b_{i}}$ is non-zero only if all $m_ {i,b_{i}} \neq 0$, which corresponds to the existence of a cycle cover in the graph.↵

We want to construct a directed graph such that the sum of the weights of its cycle covers equals $x$. Since the current problem only allows the use of $-1, 0, 1$, the edge weights can only be $1$ or $-1$, and the contribution of a valid cycle cover to the answer can only be $1$ or $-1$.↵

PS: You can refer to pages 56-58 of https://ipsc.ksp.sk/2012/real/solutions/booklet.pdf for more information.↵

</spoiler>↵


<spoiler summary="Step 2">↵

There might be many ways to construct a legal directed graph. We will demonstrate a method that transforms the problem into constructing a DAG with exactly $x$ paths from source vertex $1$ to sink vertex $n$.↵

For a directed acyclic graph $G$ with source vertex $1$ and sink vertex $n$, we can construct the following adjacency matrix:↵

- $g_{i,j} = -1$ if there is an edge $i \rightarrow j$ in $G$. Set the weight of all original edges in $G$ to $-1$.↵
- $g_{i,i} = 1$ for all $1 < i < n$. Add a self-loop with weight $1$ to all vertices in $G$ except the source and sink.↵
- $g_{n,1} = 1$. Add an edge from the sink to the source with weight $1$.↵
- Everything else $= 0$.↵

We analyze all cycle covers of this new graph. Due to the presence of the edge $n \rightarrow 1$ , any cycle cover must contain a main cycle that includes nodes $1$ and $n$, formed by a path $P$ from $1$ to $n$ in $G$ and the edge $n \rightarrow 1$. For nodes not on path $P$ (i.e., intermediate nodes not covered by path $P$), they must be covered by self-loops with weight $1$. Therefore, each cycle cover uniquely corresponds to a path $P$ from $1$ to $n$.↵

Since there are $x$ paths in $G$, we only need to ensure that the contribution of each cycle cover is $1$ to obtain a determinant value of $x$. Next, we will analyze how to achieve this by setting the weight of all original edges in $G$ to $-1$.↵

For each cycle cover, first consider the product of all edge weights:↵

- The main cycle has $k$ edges, among which $k-1$ edges come from path $P$ (each with weight $-1$), and one edge is $n \rightarrow 1$ (with weight $1$). Thus, the product term is $(-1)^{k-1}$.↵
- The weights of all other self-loops are $1$.↵

Therefore, the product of all edge weights is $(-1)^{k-1}$.↵

Then we consider the sign term $(-1)^{\mathrm{inv}(B)}$. In fact, the parity of the number of inversions $\mathrm{inv}(B)$ in the permutation is consistent with the parity of the number of even cycles in the permutation. The main cycle is a cycle of length $k$, and the self-loops are all cycles of length $1$. Therefore, the sign term is $(-1)^{k-1}$.↵

Thus, the contribution of each cycle cover is $(-1)^{k-1} \cdot (-1)^{k-1}=1$.↵

Due to the constraints in the problem that the matrix size is at most $80$ and there are at most $3$ non-zero entries per row and column, we need to construct a DAG that satisfies:↵

- Exactly $x$ paths from source vertex $1$ to sink vertex $n$.↵
- At most $80$ nodes.↵
- The in-degree of each node $\le 2$ and the out-degree of each node $\le 2$.↵

</spoiler>↵


<spoiler summary="Step 3">↵

Since $80$ is a loose boundary, there might be many constructions that satisfy it. We will introduce a construction method that encodes $x$ in base three.↵

The basic unit shown in the figure can form a base-three digit because the number of paths from $1$ to $3$ is $2$, and from $1$ to $4$ is $3$. Node $4$ can be connected to the next unit, forming a chain of units, where each unit corresponds to a base-three digit. Nodes $3$ and $4$ have one free out-degree, which can contribute to the final answer.↵

![ ](https://s21.ax1x.com/2025/09/08/pVRPStx.png)↵

The example figure below shows how to construct $22=1+3+2 \cdot 3^2$ in this way. There are $\log_3 n$ basic units, each with $4$ nodes. The answer chain has at most $\log_3 n$ nodes. Therefore, the total number of nodes is $5\log_3 n + O(1)$, which can pass the problem.↵

![ ](https://s21.ax1x.com/2025/09/08/pVRPph6.png)↵

</spoiler>↵


<spoiler summary="Code (C++)">↵
```cpp↵
#include<bits/stdc++.h> ↵
using namespace std;↵
const int N=81;↵
int a[N][N];↵
vector<pair<int,int>> e;↵
void add(int x,int y){↵
    e.push_back({x,y});↵
}↵
void make_matrix(int n){↵
    for(int i=2;i<n;++i) a[i][i]=1;↵
    a[n][1]=1;↵
    for(auto [x,y]:e) a[x][y]=-1;↵
}↵
int main(){↵
    int _; scanf("%d",&_); //cin>>_;↵
    int max_bit=15;↵
    while(_--){↵
        memset(a,0,sizeof(a)); e.clear();↵
        int n=1;↵
        for(int i=0;i<max_bit;++i){↵
            add(n,n+1); add(n+1,n+2); add(n+2,n+3); add(n+3,n+4);↵
            add(n+1,n+3); add(n+2,n+4);↵
            n+=4;↵
        }↵
        int x,bit_1=1,bit_2=4; scanf("%d",&x); ++n;↵
        for(int i=0;i<max_bit;++i){↵
            if (x%3==1) add(bit_1,n),add(n,n+1),++n;↵
            if (x%3==2) add(bit_2,n),add(n,n+1),++n;↵
            bit_1+=4; bit_2+=4; x/=3;↵
        }↵
        make_matrix(n);↵
        cout << n <<'\n';↵
        for (int r = 1; r <= n; r++) {↵
            for (int c = 1; c <= n; c++) {↵
                printf("%d ",a[r][c]);↵
            }↵
            cout << '\n';↵
        }↵
    }↵
}↵
```↵
</spoiler>↵

</spoiler>↵

<spoiler summary="Solution 2">↵

<spoiler summary="Step 1">↵

We can consider using Tridiagonal Matrices, where the advantage lies in transforming the calculation of the determinant value into a recursive formula.↵

Let $d_{i,j}$ denote the element in the i-th row and j-th column of matrix $D$, $D_k$ represents the submatrix composed of the upper-left $k \times k$ elements, and $A_k$ denotes the determinant value of $D_k$.↵

When $k \ge 2$, there are two ways to obtain $D_{k+1}$ from $D_k$:↵

- Let $ d_{k+1,k+1}=1, d_{k+1,k}=1,d_{k,k+1}=1$ to get $A_{k+1}=A_k-A_{k-1}$↵
- Let $ d_{k+1,k+1}=1, d_{k+1,k}=1,d_{k,k+1}=-1$ to get $A_{k+1}=A_k+A_{k-1}$↵

Thus, we transform the problem into constructing a sequence $A_1,\ldots,A_m$ satisfying:↵

- $A_1 = |D_1|, A_2 = |D_2|$↵
- For any $k=2,3,\ldots,m-1$, one of the following two equations holds: $A_{k+1}=A_k-A_{k-1}$, or $A_{k+1}=A_k+A_{k-1}$↵
- $A_m=n (m \le 80)$↵

</spoiler>↵


<spoiler summary="Step 2">↵

Consider recursively generating the entire sequence from $A_m=n$ backwards.↵

- Choose a positive integer as $A_{m−1}$.↵

- At a certain moment, we have $A_k$ and $A_{k+1}$, and obtain $A_{k−1}$ as follows:↵

     If $A_k > A_{k+1}$, let $A_{k-1}=A_k-A_{k+1}$; otherwise, let $A_{k-1}=A_{k+1}-A_k$↵

     This ensures that each number in the sequence is a non-negative integer.↵

- If at some point there exist $D_1,D_2$ satisfying $A_k = |D_1|, A_{k+1} = |D_2|$, successfully finish the construction.↵

For example,if we have $A_m=7$ and $A_{m−1}=3$, the final sequence will be $1,2,3,1,4,3,7$, and we will generate the matrix as↵
$$\begin{pmatrix}↵
1 & -1 & 0 & 0 & 0 & 0 & 0 \\↵
1 & 1 & -1 & 0 & 0 & 0 & 0 \\↵
0 & 1 & 1 & 1 & 0 & 0 & 0 \\↵
0 & 0 & 1 & 1 & -1 & 0 & 0 \\↵
0 & 0 & 0 & 1 & 1 & 1 & 0 \\↵
0 & 0 & 0 & 0 & 1 & 1 & -1 \\↵
0 & 0 & 0 & 0 & 0 & 1 & 1 ↵
\end{pmatrix}$$ ↵
Denote $(A_k,A_{k+1})=(x,y)$.↵

When $x>y$, the recursion process can be written as $(x,y) \rightarrow (x-y,x) \rightarrow (y,x-y)$, increasing the length of the sequence by $2$, completing one iteration of subtraction.↵

When $x \le y$, the recursion process can be written as $(x,y) \rightarrow (y-x,x)$, increasing the length of the sequence by $1$, completing one iteration of subtraction.↵

The process will eventually lead to $(x,0)$ or $(0,x)$, where $x$ is the GCD of  $A_m$ and $A_{m−1}$.↵

When $A_m$ and $A_{m−1}$ are coprime, we have $x=1$, meeting the requirements for the sequence. In fact, we can stop earlier when $(1,2)$, and the sequence is still legal.↵

When $A_m$ and $A_{m−1}$ are not coprime, we have $x>1$, and this method can't obtain a sequence that meets the requirements.↵

</spoiler>↵


<spoiler summary="Step 3">↵

Given $A_m=n$, we need to find a suitable $A_{m−1}$ such that the length of the final sequence is less than or equal to $80$.↵

Since $80$ is a relaxed constraint, and you only need to find one valid $A_{m−1}$, you can try various approaches. ↵

For example, you could enumerate all possibilities within the range $[1, n-1]$ for some large $n$, and then discover that there are many valid $A_{m−1}$ values that meet the criteria. ↵

If you randomly search for $A_{m−1}$ within the range, the expected number of attempts required is very low. In fact, the verification program tested all integers $n$ from $10$ to $10^7$, randomly selecting $1000$ possible $A_{m−1}$ values for each n and testing them. The results showed that in the worst case (when $n = 9827370$), there were still $24$ valid $A_{m−1}$ values that met the requirements out of the $1000$ randomly chosen values.↵

</spoiler>↵


<spoiler summary="Code (C++)">↵
Code:↵

```cpp↵
#include<bits/stdc++.h>↵
using namespace std;↵
int fl[1005],inf=1e9,cnt;↵
int work(int x,int y){↵
    int ans=0,tmp;↵
    while(y&&ans<=80){↵
        ++ans; tmp=y;↵
        if (x>y) y=x-y; else y=y-x;↵
        x=tmp;↵
    }↵
    if (x>1) return inf;↵
    return ans;↵
}↵
void gen(int x,int y){↵
    //printf("%d\n",work(x,y));↵
    vector<int> seq; seq.clear(); seq.push_back(x); seq.push_back(y);↵
    int tmp;↵
    while(!(x==2&&y==1)){↵
        tmp=y;↵
        if (x>y) y=x-y; else y=y-x;//x=tmp;↵
        x=tmp; ↵
        seq.push_back(y);↵
    }↵
    int ans[105][105]={0};↵
    int pre=seq.back(),n=1; seq.pop_back(); ans[1][1]=1;↵
    while(!seq.empty()){↵
        ++n;↵
        if (seq.back()>pre) ans[n][n]=1,ans[n][n-1]=1,ans[n-1][n]=-1;↵
        else ans[n][n]=1,ans[n][n-1]=1,ans[n-1][n]=1;↵
        pre=seq.back(); seq.pop_back();↵
    }↵
    printf("%d\n",n);↵
    for(int i=1;i<=n;++i){↵
        for(int j=1;j<=n;++j){↵
            printf("%d ",ans[i][j]);↵
        }↵
        printf("\n");↵
    }↵
}↵
int main(){↵
    int _; cin>>_; mt19937 rd(time(0));↵
    while(_--){↵
        int n; cin>>n;↵
        if (n==0) {printf("1\n0\n"); continue;}↵
        if (n==1) {printf("1\n1\n"); continue;}↵
        while(1){↵
            int y=rd()%(n-1)+1;↵
            int tmp=work(n,y);↵
            if (tmp<=80) {gen(n,y); break;}↵
        }↵
    }↵
    return 0;↵
}↵
```↵

Verification Program:↵

```cpp↵
#pragma GCC optimize(3)↵
#include<bits/stdc++.h>↵
using namespace std;↵
int inf=1e9;↵
int work(int x,int y){↵
    int ans=0,tmp;↵
    while(y&&ans<=80){↵
        ++ans; tmp=y;↵
        if (x>y) y=x-y; else y=y-x;↵
        x=tmp;↵
    }↵
    if (x>1) return inf;↵
    return ans;↵
}↵
int main(){↵
    mt19937 rd(114514);↵
    int n=1e7,minn=1e3;↵
    for(int x=n;x>=5;x--){↵
        int _=1e3,c=0;↵
        while(_--){↵
            int y=rd()%(x-1)+1;↵
            int tmp=work(x,y);↵
            if (tmp<=80) ++c;↵
        }↵
        if (c<minn) minn=c,cout<<' '<<minn<<' '<<x<<endl;↵
        if (x%10000==1) cout<<clock()<<'#'<<x<<endl;↵
    }↵
    return 0;↵
}↵
```↵
</spoiler>↵

</spoiler>↵

<spoiler summary="Rate this problem">↵

- Amazing problem: [likes:41]↵
- Good problem: [likes:42]↵
- Average problem: [likes:43]↵
- Bad problem: [likes:44]↵
- Horrible problem: [likes:45]↵

</spoiler>↵

[2139E2 &mdash; Determinant Construction (Hard Version)](https://mirror.codeforces.com/contest/2138/problem/E2)↵

Idea: [user:wjy666,2025-09-08]↵
Preparation: [user:wjy666,2025-09-08]↵

Since $50$ is a very tight constraint, the author did not find a method to construct the DAG for G2 as in Solution 1 of G1. If you have a better solution, please leave a comment below.↵

<spoiler summary="Hint">↵

In Solution 2, the first two steps remain consistent with G1, but we need a better method to find a suitable $A_{m−1}$ such that the length of the final sequence is less than or equal to $50$. Randomly searching for $A_{m−1}$ within the range $[1, n-1]$ may result in TLE.↵

We noticed that if $A_{m−1}$ and $A_m$ are two adjacent fibonacci numbers, the sequence will converge rapidly (with a length within $40$). Although not all $A_m=n$ are fibonacci numbers, we can still draw inspiration from this.↵

</spoiler>↵

<spoiler summary="Solution A">↵

We attempt to decompose $n$ as $n=a \cdot \operatorname{fib}(i)+b \cdot \operatorname{fib}(i-1), a,b \ge 0$, where $\operatorname{fib}(i)$ denotes the $i$-th fibonacci number.↵

Then, we set $A_{m-1}=a \cdot \operatorname{fib}(i-1)+b \cdot \operatorname{fib}(i-2)$↵

By iterating further, we obtain $A_{m-2}=a \cdot \operatorname{fib}(i-2)+b \cdot \operatorname{fib}(i-3)$, $\dots$↵

The purpose of this is to make the iteration process rapidly decrease the value in the initial steps, similar to the fibonacci sequence. Intuitively, the larger the $i$ chosen, the higher the probability of finding a legal $A_{m-1}$.↵

The author did not provide a rigorous mathematical proof for this, but using a verification program which found a legal $A_{m-1}$ for all $A_m=n \in [2,10^7]$ within one minute. Therefore, it is feasible to prove the correctness of this approach within the data range during the contest.↵

<spoiler summary="Code (C++)">↵
```cpp↵
#include<bits/stdc++.h>↵
using namespace std;↵
int fl[1005],inf=1e9,cnt;↵
int work(int x,int y){↵
    int ans=0,tmp;↵
    while(y&&ans<=50){↵
        ++ans; tmp=y;↵
        if (x>y) y=x-y; else y=y-x;↵
        x=tmp;↵
    }↵
    if (x>1) return inf;↵
    return ans;↵
}↵
void gen(int x,int y){↵
    //printf("%d\n",work(x,y));↵
    vector<int> seq; seq.clear(); seq.push_back(x); seq.push_back(y);↵
    int tmp;↵
    while(!(x==2&&y==1)){↵
        tmp=y;↵
        if (x>y) y=x-y; else y=y-x;//x=tmp;↵
        x=tmp; ↵
        seq.push_back(y);↵
    }↵
    int ans[55][55]={0};↵
    int pre=seq.back(),n=1; seq.pop_back(); ans[1][1]=1;↵
    while(!seq.empty()){↵
        ++n;↵
        if (seq.back()>pre) ans[n][n]=1,ans[n][n-1]=1,ans[n-1][n]=-1;↵
        else ans[n][n]=1,ans[n][n-1]=1,ans[n-1][n]=1;↵
        pre=seq.back(); seq.pop_back();↵
    }↵
    printf("%d\n",n);↵
    for(int i=1;i<=n;++i){↵
        for(int j=1;j<=n;++j){↵
            printf("%d ",ans[i][j]);↵
        }↵
        printf("\n");↵
    }↵
}↵
typedef long long ll;↵
ll fib[55]={1,1};↵
ll exgcd(ll a,ll b,ll &x,ll &y){↵
if(!b){↵
x=1; y=0; return a;↵
}↵
ll d=exgcd(b,a%b,y,x);↵
y-=(a/b)*x;↵
return d;↵
}↵
map<int,int> mp;↵
int main(){↵
    for(int i=2;i<=50;++i) fib[i]=fib[i-1]+fib[i-2];↵
    int _; cin>>_;↵
    while(_--){↵
        int n; cin>>n;↵
        if (n==0) {printf("1\n0\n"); continue;}↵
        if (n==1) {printf("1\n1\n"); continue;}↵
        if (n<=10){↵
            gen(n,n-1); continue;↵
        }↵
        if (mp[n]) {gen(n,mp[n]); continue;}↵
        int noww=0;↵
        while(fib[noww]<n) ++noww;↵
        int now=noww;↵
        while(now>=3){↵
            ll a=fib[now-1],b=fib[now-2],x,y,c=n;↵
            ll d=exgcd(a,b,x,y);↵
            x*=c,y*=c;↵
            //find x,y↵
            x=(x%b+b)%b;  y=(c-a*x)/b; if (y<0) {--now; continue;}↵
            int s=inf,o;↵
            while(y>=0){↵
                o=fib[now-2]*x+fib[now-3]*y;↵
                s=work(n,o);↵
                if (s>50) {x+=b,y-=a; continue;}↵
                else break;↵
            }↵
            if (s>50) {--now; continue;}↵
            else{↵
                gen(n,o); mp[n]=o; break;↵
            }↵
        }↵
        //↵
    }↵
    return 0;↵
}↵
```↵
</spoiler>↵

</spoiler>↵

<spoiler summary="Solution B">↵

We note that for the fibonacci sequence, $\lim_{x \to \infty} \frac{\operatorname{fib}(x-1)}{\operatorname{fib}(x)} = \frac{\sqrt 5 -1}{2}$, which suggests that searching for $A_{m-1}$ around $\frac{\sqrt 5 -1}{2}n$ might be a promising approach.↵

In fact, directly enumerating $A_{m-1}$ starting from $\frac{\sqrt 5 -1}{2}n$ and trying each one is a efficient method. The author also verified through a verification program that for all $A_m=n \in [2,10^7]$, a legal $A_{m-1}$ was found within one minute. Thus, it is feasible to prove the correctness of this approach within the data range during the contest.↵

Considering that the time limit for this problem is relatively loose (5s), most attempts to search for $A_{m-1}$ around $\frac{\sqrt 5 -1}{2}n$ may be able to pass.↵

<spoiler summary="Code (C++)">↵
```cpp↵
#include<bits/stdc++.h>↵
using namespace std;↵
int fl[1005],inf=1e9,cnt;↵
int work(int x,int y){↵
    int ans=0,tmp;↵
    while(y&&ans<=50){↵
        ++ans; tmp=y;↵
        if (x>y) y=x-y; else y=y-x;↵
        x=tmp;↵
    }↵
    if (x>1) return inf;↵
    return ans;↵
}↵
void gen(int x,int y){↵
    //printf("%d\n",work(x,y));↵
    vector<int> seq; seq.clear(); seq.push_back(x); seq.push_back(y);↵
    int tmp;↵
    while(!(x==2&&y==1)){↵
        tmp=y;↵
        if (x>y) y=x-y; else y=y-x;//x=tmp;↵
        x=tmp; ↵
        seq.push_back(y);↵
    }↵
    int ans[55][55]={0};↵
    int pre=seq.back(),n=1; seq.pop_back(); ans[1][1]=1;↵
    while(!seq.empty()){↵
        ++n;↵
        if (seq.back()>pre) ans[n][n]=1,ans[n][n-1]=1,ans[n-1][n]=-1;↵
        else ans[n][n]=1,ans[n][n-1]=1,ans[n-1][n]=1;↵
        pre=seq.back(); seq.pop_back();↵
    }↵
    printf("%d\n",n);↵
    for(int i=1;i<=n;++i){↵
        for(int j=1;j<=n;++j){↵
            printf("%d ",ans[i][j]);↵
        }↵
        printf("\n");↵
    }↵
}↵
map<int,int> mp;↵
int main(){↵
    int _; cin>>_;↵
    while(_--){↵
        int n; cin>>n;↵
        if (n==0) {printf("1\n0\n"); continue;}↵
        if (n==1) {printf("1\n1\n"); continue;}↵
        if (mp[n]) {gen(n,mp[n]); continue;}↵
        double s=(sqrt(5)-1.0)/2.0;↵
        int st=s*n,l=max(1,st),r=n-1;↵
        //int l=1,r=n-1;↵
        int nowy,nows=50;↵
        if (n%2==0){↵
            if (l%2==0) ++l;↵
            for(int y=l;y<=r;y+=2){↵
                int tmp=work(n,y);↵
                if (tmp<=nows) {gen(n,y); mp[n]=y; break;}↵
            }↵
        }↵
        else{↵
            for(int y=l;y<=r;++y){↵
                int tmp=work(n,y);↵
                if (tmp<=nows) {gen(n,y); mp[n]=y; break;}↵
            }↵
        }↵
    }↵
    return 0;↵
}↵
```↵
</spoiler>↵

</spoiler>↵

<spoiler summary="Rate this problem">↵

- Amazing problem: [likes:46]↵
- Good problem: [likes:47]↵
- Average problem: [likes:48]↵
- Bad problem: [likes:49]↵
- Horrible problem: [likes:50]↵

</spoiler>↵

[2139F &mdash; Ode to the Bridge Builder](https://mirror.codeforces.com/contest/2138/problem/F)↵

Idea: [user:installb,2025-09-08]↵
Preparation: [user:installb,2025-09-08]↵

<spoiler summary="Solution">↵

For convenience, we mark the targets point and the points on the initial segment with $A(0,0),B(1,0),C(p,q)$.↵

The problem asks us to do at most $\left\lceil 2|AC|\right\rceil$ moves. This constraint is actually not quite usual. We can first show that the theoretical lower bound should be $x=\left\lceil |AC|\right\rceil+\left\lceil |BC|\right\rceil−1$. We can show we can't get less moves by following: If we have already constructed the final structure, then $AC$ and $BC$ should be connected with a path, and we can find a path from $A$ to $C$ and a path from $B$ to $C$ that don't intersect (except at point $C$), otherwise the structure can't be built with non-degenerate triangles.↵

And we have to alternate progressing through two paths every time we construct a triangle, otherwise we must draw a line longer than $1$. The last triangle will cover both paths, so the number of steps will be decreased by one. The optimal path is two straight segments (which is not always possible).↵

**Case 1.1:** We first try some simple strategies. Two triangles can form a parallelogram, so we can connect $AC$, choose a point $D$ on $AC$ which makes $|AD|=\frac{|AC|}{\lceil|AC|\rceil}$, which is always in range $[0.5,1]$ when $|AC|\ge 1$. And from $\triangle ADB$ we can construct a parallelogram. We draw a line passing $D$ that is parallel to $AB$, a line passing $B$ that is parallel to $AC$, and they intersects at $E$. Then we pile up the same parallelogram structure until we reach $C$. This always works when $30^\circ\le\angle CAB\le60^\circ$.↵

Proof: We first prove that all segments has length between $0.5$ and $1$. Because we stack the same parallelogram structure, all segments have length equal to $AB,BD$ or $AD$. $AB$ and $AD$ already meets the requirement. When $30^\circ\le\angle CAB\le60^\circ$, the length of $BD$ is at least $0.5$ as the distance between two parallel lines is at least $0.5$, and at most $1$ as $AB=1$ and $\angle CAB$ is never the largest angle in $\triangle DAB$. We can calculate that the number of moves we used is $2\left\lceil |AC|\right\rceil-1\le\left\lceil 2|AC|\right\rceil$ which matches the requirement (for the last parallelogram we only need one triangle).↵

![ ](https://s21.ax1x.com/2025/09/07/pV2wJnU.png)↵

**Case 1.2:** We can change the way we construct parallelograms (with sides $AB,BC$) and this method always works when $30^\circ\le\angle CBx\le60^\circ$. The number of moves is $\left\lceil2|BC|\right\rceil\le \left\lceil 2|AC|\right\rceil$. This case is actually necessary, which will be explained in the following part.↵

![ ](https://s21.ax1x.com/2025/09/07/pV204IJ.png)↵

**Case 2:** If $\angle CAB< \angle CBx<30^\circ$. We first build a point $D$ which makes $AD=1$ and $\angle DAB=30^\circ$ and construct $\triangle DAB$. ↵

We can show that the constraint is actually easier to meet in this situation, because when $\angle CAB<\angle CBx<30^\circ$, $|BC|<|AC|-0.5$. With this, $\left\lceil |AC|\right\rceil+\left\lceil |BC|\right\rceil−1=\left\lceil 2|AC|\right\rceil-1$ always holds, allowing us one extra move.↵

Then we draw a line passing $D$ parallel to $BC$. We can show that if $\angle DAB=30^\circ$ and $0\le \angle CAB\le 30^\circ$, the distance from $D$ to line $BC$ is at least $0.5$. So all segments with ends on different lines will have length $\ge 0.5$.↵

Then we select a point $E$ on $BC$, which makes $DE=1$. We can show that $\sqrt{3}-1\le |BE|\le 1$ based on some calculations in this case. Then we do a similar parallelogram construction process to $C$. The total number of moves is $2\left\lceil |CE|\right\rceil+2$.↵

There are still two cases here to analyze to prove the number of steps fulfills our requirement. We write $|BC|=a+b$ where $a$ is the integer part of $|BC|$, then we analyze cases about $b$.↵

- Case 2.1: When $b\ge\sqrt{3}-1$ or $b=0$, we can show that $2\left\lceil |AC|\right\rceil=\left\lceil 2|AC|\right\rceil$, and $\left\lceil |AC|\right\rceil=\left\lceil |BC|\right\rceil+1$ if $|AC|\ge 2$. The number of steps is $2\left\lceil |EC|\right\rceil+2\le 2\left\lceil |BC|\right\rceil+2=2\left\lceil |AC|\right\rceil$. ↵

- Case 2.2: When $0<b<\sqrt{3}-1$, we can show that $\left\lceil |EC|\right\rceil=\left\lceil |BC|\right\rceil-1$. Total moves equals to $2+2\left\lceil |CE|\right\rceil=2\left\lceil |BC|\right\rceil\le \left\lceil |AC|\right\rceil+\left\lceil |BC|\right\rceil=\left\lceil 2|AC|\right\rceil$. ↵

Be careful with small cases where $|BC|$ is too short, which may make $|DF|=|EG|<0.5$.↵

Note that there are some cases where $\angle CBx>30^\circ$ and $\angle CAB<30^\circ$, where Case 2 strategy doesn't work. So case 1.2 is required.↵

![ ](https://s21.ax1x.com/2025/09/07/pV2wUAJ.png)↵

**Case 3:** If $\angle CBx>\angle CAB>60^\circ$. We first build a point $D$ which makes $AD=1$ and $\angle DAB=60^\circ$ and construct $\triangle DAB$. We write $|AC|=a+b$ where $a$ is integer, then we analyze two cases about $b$.↵

**Case 3.1:** When $b>0.5$ or $b=0$, $2\left\lceil |AC|\right\rceil=\left\lceil 2|AC|\right\rceil$. We begin a same parallelogram construction as Case 1 where the sides of parallelogram are $BC,BD$. We can show that $30^\circ\le\angle CBD\le60^\circ$. So it is possible to pile up to $C$ from $BD$ in $2\left\lceil |BC|\right\rceil-1$ moves. And in total we need $2\left\lceil |BC|\right\rceil\le2\left\lceil |AC|\right\rceil=\left\lceil 2|AC|\right\rceil$ moves.↵

![ ](https://s21.ax1x.com/2025/09/07/pV2wYBF.png)↵

**Case 3.2:** When $0<b\le 0.5$, $2\left\lceil |AC|\right\rceil=\left\lceil 2|AC|\right\rceil+1$. We instead connect $CD$ and construct parallelogram with sides $DC,DB$. We can show that $120^\circ\le\angle CDB\le150^\circ$ so we can still do the parallelogram construction. When $|AC|\ge \sqrt{3}$, $\left\lceil |CD|\right\rceil=\left\lceil |AC||\right\rceil-1$, making the number of moves $2\left\lceil |CD|\right\rceil+1=2\left\lceil |AC|\right\rceil-1=\left\lceil 2|AC|\right\rceil$. ↵

![ ](https://s21.ax1x.com/2025/09/07/pV2wt74.png)↵

Actually case 1.1 is not required, because it is impossible to construct a testcase where $\angle CAB<60^\circ, \angle CBx>60^\circ,0<b\le 0.5$ and Case 3.2 fails.↵

</spoiler>↵

<spoiler summary="Code (C++)">↵

```cpp↵
#include <bits/stdc++.h>↵
using namespace std;↵
typedef double db;↵
const db pi = acos(-1.0);↵
const int N = 1000005;↵

inline int sgn(db x){↵
    if(x < 1e-13 && x > -1e-13) return 0;↵
    if(x > 0) return 1;↵
    return -1;↵
}↵

struct point{↵
    db x,y;↵
    point (db _x = 0.0,db _y = 0.0) : x(_x), y(_y) {}↵
};↵
point operator + (const point &p1,const point &p2){↵
return point(p1.x + p2.x,p1.y + p2.y);↵
}↵
point operator - (const point &p1,const point &p2){↵
return point(p1.x - p2.x,p1.y - p2.y);↵
}↵
point operator * (db x,const point &p){↵
return point(x * p.x,x * p.y);↵
} ↵
bool operator == (point x,point y){↵
return sgn(x.x - y.x) == 0 && sgn(x.y - y.y) == 0;↵
}↵

inline db dot(point p1,point p2){↵
    return p1.x * p2.x + p1.y * p2.y;↵
}↵

inline db det(point p1,point p2){↵
return p1.x * p2.y - p2.x * p1.y;↵
}↵

inline db len(point p){↵
    return sqrtl(1.0 * p.x * p.x + 1.0 * p.y * p.y);↵
}↵

point project_point(point x,point ya,point yb){↵
point v = yb - ya;↵
return ya + (dot(v,x - ya) / dot(v,v)) * v;↵
}↵

db distp(point x,point ya,point yb){↵
return fabs(det(ya - x,yb - x)) / len(yb - ya);↵
}↵

point line_circle_intersec_point(point o,point la,point lb){↵
db dis = distp(o,la,lb),l;↵
point pj = project_point(o,la,lb);↵
l = sqrt(1.0 - dis * dis);↵
point ret = pj + (l / len(lb - la)) * (lb - la);↵
return ret;↵
}↵

tuple <int,int,int> ans[N];↵
point p[N],target;↵
int step;↵

bool check(int n){↵
    set <pair <int,int> > st;↵
    st.insert({1,2});↵
    if(n > step) return 0;↵
    db eps_len = 1e-8,eps_dis = 1e-4;↵
    int fl = 0;↵
    for(int i = 1;i <= n;i ++){↵
        auto [u,v,w] = ans[i];↵
        if(u > v) swap(u,v);↵
        if(st.find({u,v}) == st.end()) return 0;↵
        if(len(p[u] - p[w]) < 0.5 - eps_len || len(p[u] - p[w]) > 1.0 + eps_len) return 0;↵
        if(len(p[v] - p[w]) < 0.5 - eps_len || len(p[v] - p[w]) > 1.0 + eps_len) return 0;↵
        st.insert({u,w}); st.insert({v,w});↵
        if(len(p[w] - target) <= eps_dis) fl = 1;↵
    }↵
    return 1;↵
}↵

int solve1a(){↵
    point dir = target - p[1];↵
    int split = ceil(len(dir) - 1e-9);↵
    int c = 2;↵
    for(int i = 1;i < split;i ++){↵
        ++ c; p[c] = p[1] + (1.0 * i / split) * dir;↵
        ans[c - 2] = {c - 2,c - 1,c};↵
        ++ c; p[c] = p[2] + (1.0 * i / split) * dir;↵
        ans[c - 2] = {c - 2,c - 1,c};↵
        // construct one parallelogram↵
    }↵
    ++ c; p[c] = target;↵
    ans[c - 2] = {c - 2,c - 1,c};↵
    if(check(c - 2)) return c - 2;↵
    return 0;↵
}↵

int solve1b(){↵
    point dir = target - p[2];↵
    int split = ceil(len(dir) - 1e-9);↵
    int c = 2;↵
    for(int i = 1;i <= split;i ++){↵
        ++ c; p[c] = p[1] + (1.0 * i / split) * dir;↵
        ans[c - 2] = {c - 2,c - 1,c};↵
        ++ c; p[c] = p[2] + (1.0 * i / split) * dir;↵
        ans[c - 2] = {c - 2,c - 1,c};↵
    }↵
    if(check(c - 2)) return c - 2;↵
    return 0;↵
}↵

int solve2(){↵
    p[3] = point(sqrt(3.0) / 2,0.5);↵
    p[4] = line_circle_intersec_point(p[3],p[2],target);↵
    if(len(p[4] - p[2]) > 1)↵
        p[4] = p[2] + (1.0 / len(target - p[2])) * (target - p[2]);↵
    ans[1] = {1,2,3};↵
    ans[2] = {2,3,4};↵
    point dir = target - p[4];↵
    int split = ceil(len(dir) - 1e-9);↵
    int c = 4;↵
    for(int i = 1;i <= split;i ++){↵
        ++ c; p[c] = p[3] + (1.0 * i / split) * dir;↵
        ans[c - 2] = {c - 2,c - 1,c};↵
        ++ c; p[c] = p[4] + (1.0 * i / split) * dir;↵
        ans[c - 2] = {c - 2,c - 1,c};↵
    }↵
    if(check(c - 2)) return c - 2;↵
    return 0;↵
}↵

int solve3a(){↵
    p[3] = point(0.5,sqrt(3.0) / 2);↵
    ans[1] = {1,2,3};↵
    point dir = target - p[2];↵
    int split = ceil(len(dir) - 1e-9);↵
    int c = 3;↵
    for(int i = 1;i < split;i ++){↵
        ++ c; p[c] = p[2] + (1.0 * i / split) * dir;↵
        ans[c - 2] = {c - 2,c - 1,c};↵
        ++ c; p[c] = p[3] + (1.0 * i / split) * dir;↵
        ans[c - 2] = {c - 2,c - 1,c};↵
    }↵
    ++ c; p[c] = target;↵
    ans[c - 2] = {c - 2,c - 1,c};↵
    if(check(c - 2)) return c - 2;↵
    return 0;↵
}↵

int solve3b(){↵
    p[3] = point(0.5,sqrt(3.0) / 2);↵
    ans[1] = {1,2,3};↵
    point dir = target - p[3];↵
    int split = ceil(len(dir) - 1e-9);↵
    int c = 3;↵
    for(int i = 1;i <= split;i ++){↵
        ++ c; p[c] = p[2] + (1.0 * i / split) * dir;↵
        ans[c - 2] = {c - 2,c - 1,c};↵
        ++ c; p[c] = p[3] + (1.0 * i / split) * dir;↵
        ans[c - 2] = {c - 2,c - 1,c};↵
    }↵
    if(check(c - 2)) return c - 2;↵
    return 0;↵
}↵

int solve(){↵
    if(int res = solve1a()) return res;↵
    if(int res = solve1b()) return res;↵
    if(int res = solve2()) return res;↵
    if(int res = solve3a()) return res;↵
    if(int res = solve3b()) return res;↵
    return 0;↵
}↵

int main(){↵
    int TC; scanf("%d",&TC);↵
    p[1] = point(0,0);↵
    p[2] = point(1,0);↵
    while(TC --){↵
        int tx,ty;↵
        scanf("%d %d %d",&tx,&ty,&step);↵
        step = ceil(2.0 * sqrt(1.0 * tx * tx + 1.0 * ty * ty));↵
        target = point(tx,ty);↵
        int n = solve();↵
        assert(n > 0);↵
        printf("%d\n",n);↵
        for(int i = 1;i <= n;i ++){↵
            auto [u,v,w] = ans[i];↵
            printf("%d %d %.12lf %.12lf\n",u,v,p[w].x,p[w].y);↵
        }↵
    }↵
    return 0;↵
}↵
```↵
</spoiler>↵

<spoiler summary="Rate this problem">↵

- Amazing problem: [likes:51]↵
- Good problem: [likes:52]↵
- Average problem: [likes:53]↵
- Bad problem: [likes:54]↵
- Horrible problem: [likes:55]↵

</spoiler>↵

History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
en33 English installb 2025-09-09 19:46:59 0 (published)
en32 English installb 2025-09-09 19:43:46 23
en31 English installb 2025-09-09 19:40:59 27
en30 English installb 2025-09-09 19:34:14 51 (saved to drafts)
en29 English installb 2025-09-08 23:47:06 0 (published)
en28 English installb 2025-09-08 23:46:22 18
en27 English installb 2025-09-08 23:45:53 25
en26 English installb 2025-09-08 23:42:42 68
en25 English installb 2025-09-08 23:41:12 960
en24 English installb 2025-09-08 23:39:17 850
en23 English installb 2025-09-08 23:37:43 85
en22 English installb 2025-09-08 23:36:46 160
en21 English installb 2025-09-08 23:24:43 8140
en20 English installb 2025-09-08 23:23:08 8644 Reverted to en14
en19 English installb 2025-09-08 23:22:08 67
en18 English installb 2025-09-08 23:20:21 64
en17 English installb 2025-09-08 23:14:11 62
en16 English installb 2025-09-08 23:13:02 103
en15 English installb 2025-09-08 23:11:29 8424
en14 English wjy666 2025-09-08 22:43:26 5984
en13 English installb 2025-09-08 22:30:36 9
en12 English installb 2025-09-08 22:27:35 896
en11 English installb 2025-09-08 22:21:03 29
en10 English installb 2025-09-08 22:20:01 1173
en9 English installb 2025-09-08 22:13:25 291
en8 English installb 2025-09-08 22:08:55 3404
en7 English installb 2025-09-08 21:06:11 18537
en6 English installb 2025-09-08 20:58:41 82
en5 English installb 2025-09-08 20:57:39 2532
en4 English installb 2025-09-08 20:50:17 2041
en3 English installb 2025-09-08 20:47:06 13186
en2 English installb 2025-09-08 20:44:29 913 Tiny change: '1' -> '\n~~~~~\nYour code here...\n~~~~~\n\n``'
en1 English installb 2025-09-08 19:38:01 10 Initial revision (saved to drafts)