---
# System prepended metadata

title: Editorial for Pre Tuyển Sinh 1

---

# Editorial for Pre Tuyển Sinh 1
[A1 - Robot di chuyển](https://codeforces.com/gym/522403/problem/A1)

Ta chỉ cần khởi tạo $x = 0, y = 0$ và các theo tác sau:
* $L : x = x - a$
* $R : x = x + a$
* $U : y = y + a$
* $D : y = y - a$

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

using namespace std;

long long x = 0, y = 0;

signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    
    freopen("TRAVEL.INP","r",stdin);
    freopen("TRAVEL.OUT","w",stdout);
    
    int t;
    cin >> t;
    while (t--)
    {
        char c;
        long long a;
        cin >> c >> a;
        if (c == 'L') x = x - a;
        if (c == 'R') x = x + a;
        if (c == 'U') y = y + a;
        if (c == 'D') y = y - a;
    }
    
    cout << x << ' ' << y;
    
    return 0;
}
```

[A2 - Bật đèn](https://codeforces.com/gym/522403/problem/A2)

Với subtask đầu tiên có $n,q \le 10^3$ ta có thể dùng brute-force để giải quyết bài toán với độ phức tạp thời gian $O(2q(r - l + 1))$ $=>$ $O(nq)$

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

using namespace std;

const int maxN = 1e6 + 17;
int n,q;
int a[maxN];

signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    
    freopen("LIGHTS.INP","r",stdin);
    freopen("LIGHTS.OUT","w",stdout);
    
    cin >> n >> q;
    for (int i = 1; i <= n; ++i) cin >> a[i];
    
    while (q--)
    {
        int l,r;
        cin >> l >> r;
        int res = 0;
        
        //Xét 0 1 0 1 ...
        int curr = 0, ans = 0;
        for (int i = l; i <= r; ++i)
        {
            if (curr == a[i]) ++ans;
            curr = !curr;
        }
        res = ans;
        
        //Xét 1 0 1 0 ...
        curr = 1, ans = 0;
        for (int i = l; i <= r; ++i)
        {
            if (curr == a[i]) ++ans;
            curr = !curr;
        }
        
        cout << min(res,ans) << endl;
    }
    
    return 0;
}
```

Đối với subtask 2 thì không thể dùng thuật với độ phức tạp $O(nq)$ nên cần phải có 1 thuật khác để tối ưu hóa thuật toán.

1 trong những cách tối ưu là dùng prefix sum. Ta có thể tính toán trước những bóng đèn nào thỏa mãn trong 2 trường hợp 1010 và 0101. Và khi xử lý mỗi truy vấn ta chỉ cần thực hiện việc đó trong $O(1)$. Vậy tổng thể của thuật toán này là $O(n + q)$.

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

using namespace std;

const int maxN = 1e6 + 17;
int n,q;
int a[maxN], odd[maxN], even[maxN];

signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    
    freopen("LIGHTS.INP","r",stdin);
    freopen("LIGHTS.OUT","w",stdout);
    
    cin >> n >> q;
    for (int i = 1; i <= n; ++i) cin >> a[i];
    
    //Even: xét 0101
    int curr = 0;
    for (int i = 1; i <= n; ++i)
    {
        if (curr == a[i]) even[i] = 1 + even[i - 1];
        else even[i] = even[i - 1];
        curr = !curr; //Đổi 1 thành 0 và ngược lại
    }
    
    //Odd: xét 1010
    curr = 1;
    for (int i = 1; i <= n; ++i)
    {
        if (curr == a[i]) odd[i] = 1 + odd[i - 1];
        else odd[i] = odd[i - 1];
        curr = !curr; //Đổi 1 thành 0 và ngược lại
    }
    
    while (q--)
    {
        int l,r;
        cin >> l >> r;
        cout << min(odd[r] - odd[l - 1], even[r] - even[l - 1]) << endl;
    }
    
    return 0;
}
```

[A3 - Số thứ tự đội hình](https://codeforces.com/gym/522403/problem/A3)

Với subtask 1: $n \le 10$ ta có thể dùng brute-force để tìm số thứ tự của hoán vị ấy.

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

using namespace std;

const int maxN = 5 * 1e5 + 17;
int n;
int a[maxN];
long long ans = 0;

signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    
    freopen("PERMUTATION.INP","r",stdin);
    freopen("PERMUTATION.OUT","w",stdout);
    
    cin >> n;
    for (int i = 1; i <= n; ++i) cin >> a[i];
    
    do
    ++ans;
    while (prev_permutation(a + 1, a + 1 + n));
    
    cout << ans;
    
    return 0;
}
```
Với subtask 2,3:
Cho ví dụ $A = [3,4,1,2]$

Đầu tiên ta cho $B = [1,2,3,4]$.


Để $a[i] = 3$ trong lần đầu tiên thì cần bao nhiêu hoán vị để đạt mục tiêu?

**Cách 1: Thủ công**
Ta brute-force từ từ sẽ ra kết quả:

1. $B = [1,2,3,4]$
2. $B = [1,2,4,3]$
3. $B = [1,3,2,4]$
4. $B = [1,3,4,2]$
5. $B = [1,4,2,3]$
6. $B = [1,4,3,2]$
7. $B = [2,1,3,4]$
8. $B = [2,1,4,3]$
9. $B = [2,3,1,4]$
10. $B = [2,3,4,1]$
11. $B = [2,4,1,3]$
12. $B = [2,4,3,1]$
13. $B = [3,1,2,4]$
14. $B = [3,1,4,2]$
15. $B = [3,2,1,4]$
16. $B = [3,2,4,1]$
17. $B = [3,4,1,2]$

Vậy $ans = 17$ 

Cách 2:
Ta cần chú ý hoán vị thứ 1 và hoán vị thứ 13. Tại sao lại là hoán vị thứ 13? Vì nó có $a[1] = 3$ ngay trong lần đầu tiên. Để ý thêm 1 điều nữa là khoảng cách giữa 2 hoán vị này là 12. Nếu biến đổi một chút thí $12 = 2.3!$ ($3!$ là công thức tính hoán vị 3 phần tử, $2$ là số lượng phần tử nhỏ hơn $a[1]$ và nằm đằng sau vị trí 1. 

Quá trình thuật toán như sau:

$result = 0$

$factorial = \{0!,1!,2!,3!...,n!\}$

* Xét $i = 1$:
    
    $cnt = 0$ (số lượng phần tử nhỏ hơn $a[i]$ và nằm đằng sau vị trí i)    
    $=> cnt = 2$
    
    $result = result + factorial[n - 1]$ * cnt
    
    $result = 0 + 3!*2 = 12$
    
* Xét $i = 2$:
    
    $cnt = 0$ 
    $=> cnt = 2$
    
    $result = result + factorial[n - 2]$ * cnt
    
    $result = 12 + 2!*2 = 16$
    
* Xét $i = 3$:
    
    $cnt = 0$ 
    $=> cnt = 0$
    
    $result = result + factorial[n - 3]$ * cnt
    
    $result = 16 + 1!*0 = 16$
    
* Xét $i = 4$:
    
    $cnt = 0$ 
    $=> cnt = 4$
    
    $result = result + factorial[n - 4]$ * cnt
    
    $result = 16 + 0!*0 = 16$
    
Cuối cùng in ra kết quả là $result + 1$.

*Giải thích tại $i = 2$:*

Mặc dù có 3 số nhỏ hơn 4 nhưng số 3 nó đứng trước số 4 nên $cnt = 2$. Vì sao lại thế? Do ta không thể có hoán vị như thế này:

$[3,1,2,4]$ ... $[3,2,1,4]$ ... ~~[3,3,1,4]~~ ... $[3,4,1,2]$

$[3,3,1,4]$ không hợp lệ vì xuất hiện 2 số 3.

**Tổng thể lại kết quả của bài toán là:**

$result = 1 + \sum\limits_{i = 1}^n (factorial[n - i] * query(1,a[i] - 1))$

Với $query(1, a[i] - 1)$ là đếm số lượng các phần tử sau vị trí $i$ thỏa $(1 \le x \le a[i] - 1)$

Với độ phức tạp $O(n^2)$ thì không mấy khó khăn để full subtask 2 và 3(nhớ mod nữa đấy).

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

using namespace std;

const int maxN = 5 * 1e5 + 17;
const long long mod = 1e9 + 7;

int n;
long long a[maxN], factorial[maxN];
long long result = 0;

signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    
    freopen("PERMUTATION.INP","r",stdin);
    freopen("PERMUTATION.OUT","w",stdout);
    
    cin >> n;
    for (int i = 1; i <= n; ++i) cin >> a[i];
    
    //Khởi tạo mảng factorial
    factorial[0] = 1;
    for (int i = 1; i <= n; ++i) factorial[i] = (i * factorial[i - 1]) % mod;
    
    //Process
    for (int i = 1; i <= n; ++i)
    {
        //Đếm cnt
        long long cnt = 0;
        for (int j = i + 1; j <= n; ++j) 
            if (a[j] < a[i]) ++cnt;
            
        result = (result + factorial[n - i] * cnt) % mod;
    }
    
    cout << (result + 1) % mod;
    return 0;
}

```

Với subtask 4(chỉ để giải trí), ta có thể tối ưu việc tìm cnt thay vì trong $O(n)$ thành $O(logn)$ bằng [Fenwick tree](https://vnoi.info/wiki/algo/data-structures/fenwick.md). Khi đó, thuật toán giảm còn $O(n.logn)$.


    

