1. Abridged problem statement
Given integers n, t1, t2. Two workers A and B start at time 0 and each writes solutions repeatedly: A takes t1 time per solution, B takes t2. Whenever a worker finishes one at time s, he looks at how many total solutions have been completed up to time s (including those finishing exactly at s). If that total is strictly less than n, he immediately starts another; otherwise he stops. Already started solutions are never aborted. Compute:
- m = total solutions eventually written (possibly > n)
- f = the time when the very last solution finishes

2. Detailed editorial
We need to track two streams of finishing times: multiples of t1 and multiples of t2, merged in time order. A direct simulation (e.g. two pointers or a priority queue) will work in O(n) time but can be simplified further:

Step 1: Find the earliest time T such that the number of solutions finished by time T is at least n.
  - Let A(T) = ⌊T/t1⌋, B(T) = ⌊T/t2⌋.
  - We want the minimal T with A(T) + B(T) ≥ n.
  - Apply binary search on T in [0, 1e8]. Each step computes A(T)+B(T) in O(1). This takes O(log(max_time)).

Call that minimal time ret. By definition:
  (i) eval(ret) = A(ret) + B(ret) ≥ n,
  (ii) eval(ret–1) < n.

At time ret, some solutions may finish simultaneously. Let ret2 = eval(ret) be the total done up to ret. These are all the solutions that complete at or before ret.

Step 2: Account for in-progress jobs that were started before ret and will finish after ret.
  - At time ret, worker A is in the middle of a job if ret % t1 ≠ 0. His last finish was at ⌊ret/t1⌋·t1 < ret; since eval(ret–1) < n he must have started the next one. That job will end at FA = ret + (t1 – ret%t1).
  - Similarly for worker B: if ret % t2 ≠ 0 then he has a pending job finishing at FB = ret + (t2 – ret%t2).
Each pending job will complete no matter what, so we add one for each pending worker, and the final completion time f = max(ret, FA, FB).

Thus the answer is:
  m = ret2 + (ret%t1 ≠ 0 ? 1 : 0) + (ret%t2 ≠ 0 ? 1 : 0)
  f = maximum of ret and those pending finish times.

Time complexity: O(log(max_time)). Space: O(1).

3. C++ Solution
---------------

```cpp
#include <bits/stdc++.h>

using namespace std;

template<typename T1, typename T2>
ostream& operator<<(ostream& out, const pair<T1, T2>& x) {
    return out << x.first << ' ' << x.second;
}

template<typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& x) {
    return in >> x.first >> x.second;
}

template<typename T>
istream& operator>>(istream& in, vector<T>& a) {
    for(auto& x: a) {
        in >> x;
    }
    return in;
};

template<typename T>
ostream& operator<<(ostream& out, const vector<T>& a) {
    for(auto x: a) {
        out << x << ' ';
    }
    return out;
};

int n, t1, t2;

void read() {
    cin >> n >> t1 >> t2;
}

int eval(int x) {
    return x / t1 + x / t2;
}

void solve() {
    // By time x the total number of fully written solutions is x / t1 + x / t2
    // (each author finishes one every t1, resp. t2 units), so eval(x) is
    // monotone in x. Binary search the earliest time `ret` at which at least n
    // solutions are finished; that is the moment the last started solution can
    // make the count reach n.
    //
    // Both authors keep working as long as the count is still below n when
    // they finish, so each may already have a solution in progress that
    // completes after `ret`. If `ret` is not a multiple of t1 (resp. t2), the
    // corresponding author had an unfinished solution at `ret` that adds one
    // to the count and finishes at the next multiple; the final finishing time
    // is the latest of those completions.

    int low = 0, high = 1e8, ret = 0;
    while(low <= high) {
        int mid = (low + high) / 2;
        if(eval(mid) >= n) {
            ret = mid;
            high = mid - 1;
        } else {
            low = mid + 1;
        }
    }

    int finish = ret, total = eval(ret);
    if(ret % t1 != 0) {
        finish = max(finish, ret + t1 - ret % t1);
        total++;
    }

    if(ret % t2 != 0) {
        finish = max(finish, ret + t2 - ret % t2);
        total++;
    }

    cout << total << ' ' << finish << '\n';
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int T = 1;
    // cin >> T;
    for(int test = 1; test <= T; test++) {
        read();
        // cout << "Case #" << test << ": ";
        solve();
    }

    return 0;
}
```

4. Python solution with detailed comments
```python
def main():
    import sys
    data = sys.stdin.read().split()
    n, t1, t2 = map(int, data)

    # Function to count how many solutions by time x
    def finished(x):
        return x // t1 + x // t2

    # Binary search minimal time 'ret' where finished(ret) >= n
    low, high = 0, n * min(t1, t2)
    ret = high
    while low <= high:
        mid = (low + high) // 2
        if finished(mid) >= n:
            ret = mid
            high = mid - 1
        else:
            low = mid + 1

    # Count how many done by time ret
    total = finished(ret)
    last_time = ret

    # Check if Petya has a pending job at time ret
    if ret % t1 != 0:
        # This job will finish at next multiple of t1
        finishA = ret + (t1 - ret % t1)
        last_time = max(last_time, finishA)
        total += 1

    # Check if Vasya has a pending job
    if ret % t2 != 0:
        finishB = ret + (t2 - ret % t2)
        last_time = max(last_time, finishB)
        total += 1

    # Print result
    print(total, last_time)

if __name__ == "__main__":
    main()
```

5. Compressed editorial
- Binary search for the smallest time `T` such that `⌊T/t1⌋ + ⌊T/t2⌋ ≥ n`.
- Let `c = ⌊T/t1⌋ + ⌊T/t2⌋`. Those are the solutions done at or before `T`.
- Any worker with `T % ti != 0` was mid-job (because his last finish was before `T` when total < n) and will finish one more at time `T + (ti – T%ti)`.
- Total = `c` + number of pending jobs (0–2). Last finish = max of `T` and those pending finish times.
