Số hoán vị từ thứ một triệu của các chữ số 0, 1, 2, 3, 4, 5, 6, 7, 8 và 9 là gì?

Problem PE024-Lexicographic-permutations

A permutation is an ordered arrangement of objects. For example, 3124 is one possible permutation of the digits 1, 2, 3 and 4. If all of the permutations are listed numerically or alphabetically, we call it lexicographic order. The lexicographic permutations of 0, 1 and 2 are:

012 021 102 120 201 210

What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?

Đề bài

Một phép hoán vị là một cách sắp xếp theo thứ tự của các đối tượng.

Ví dụ, 3124 là một hoán vị có thể có của các chữ số 1, 2, 3 và 4.

Nếu tất cả các hoán vị được liệt kê bằng số hoặc theo thứ tự bảng chữ cái, chúng ta gọi nó là thứ tự từ điển. Các hoán vị từ vựng của 0, 1 và 2 là:

012 021 102 120 201 210

Hãy tìm số hoán vị từ thứ hai triệu của các chữ số 0, 1, 2, 3, 4, 5, 6, 7, 8 và 9 là gì?

Phân tích đề bài:

Phép toán hoán vị khá quen thuộc với học sinh cấp 3. Trước đây, đề thi toán khối B/D năm nào cũng có.

Để giải quyết bài toán này, chúng ta chỉ cần đặt 1 list chứa các số từ 0 - 9. Sau đó lần lượt swap các số theo thứ tự từ điển, mỗi số được sinh ra sẽ được tính là 1 đơn vị. Khi nào đặt đến 2.000.000 thì dừng lại.

Cách làm này khá kinh hoàng :

Dở lại công thức tìm số lượng hoán vị, nếu ta có N số khác nhau thì có N! hoán vị.

Ở đây chúng ta có 10 số –> 10! = 3.628.800

Nếu đặt 0 là số đầu tiên và dùng 9 số đằng sau để tạo hoán vị –> có 9! = 362.880 số được tạo ra.

Tiếp tục đặt số 1 thay thế cho số 0 ở đầu, chúng ta tiếp tục có 9! = 362.880 số hoán vị được tạo ra. …

0* : 0 - 362880
1* : 362881 - 725760
2* : 725761 - 1088640

Như danh sách trên thì số thứ 1 triệu sẽ nằm trong nhóm 2*

Ta thấy số thứ 725761 theo thứ tự từ điển là: 2013456789

Từ vị trí 725.761 đến 1.000.000 cần qua 274.239 hoán vị.

Loại bỏ số 2 ở đầu và thêm 1 số tiếp theo đi, chúng ta còn 8 số thiết lập hoán vị. Mỗi số ở vị trí thứ 2 sẽ tạo ra được 8! = 40320 hoán vị.

274239//40320 = 6

–> Cần 6 lần thay đổi vị trí số thứ 2 để đạt được vị trí ~ 1.000.000

…..

Cứ làm như vậy chúng ta sẽ lần lượt ra được kết quả.



import math

LIMIT_NUMBER = 1000000


def find_millionth_lexicographic_permutation():
    perm = [_ for _ in range(0, 10)]
    numbers = [str(_) for _ in range(0, 10)]
    count = len(perm)
    perm_num = ""
    remain = LIMIT_NUMBER - 1

    for index in range(1, 10):
        step = remain // math.factorial(count - index)
        remain = remain % math.factorial(count - index)
        perm_num = perm_num + numbers[step]
        numbers.pop(step)
        if remain == 0:
            break

    for item in numbers:
        perm_num += item

    return perm_num


Kết quả của bài toán:

Nguyens-MBP:PE-024 vinh.nguyenquang$ python3 millionth_lexicographic_permutation.py
The 1000000st lexicographic permutation is: 2783915460
elapsed time: 2.47955322265625e-05s

Con số về thời gian khá ấn tượng

Source-code: PE-024