Toán học, 79 byte
Min[2#/(d=Divisors@#~Cases~_?OddQ)+d]-2⌊(2#)^.5+.5⌋+⌈Sqrt[8#+1]~Mod~1⌉&
Giải trình
Tôi không thể bận tâm để thực hiện thuật toán trong thử thách, vì vậy tôi muốn tìm một lối tắt cho giải pháp. Trong khi tôi tìm thấy một điều, thật không may, nó không đánh bại câu trả lời Mathicala thực hiện thuật toán. Điều đó nói rằng, tôi chắc chắn rằng điều này chưa được đánh gôn tối ưu, và có thể có những ngôn ngữ khác có thể hưởng lợi từ phương pháp này hoặc một số hiểu biết thu được trong quá trình này.
Vì vậy, tôi khẳng định rằng chuỗi chúng ta phải tính toán là:
f (n) = 2 * ( A212652 (n) - A002024 (n)) + 1 + A023532 (n-1)
Ngoài ra, đó là f (n) = 1 nếu n là số tam giác và f (n) = 2 * ( A212652 (n) - A002024 (n) + 1) nếu không.
Trong biểu thức đầu tiên, A023532 chỉ đơn giản mã hóa hai trường hợp khác nhau này. Hai dãy còn lại (cộng 1) là sự khác biệt giữa số nguyên k lớn nhất trong phép phân tách dài nhất của n thành các số nguyên liên tiếp (k-i + 1) + (k-i + 2) + ... + k = n và số nguyên j lớn nhất sao cho 1 + 2 + ... + j <n .
Nói một cách đơn giản hơn một chút, đây là cách chúng ta tìm thấy câu trả lời cho số phi tam giác: thứ nhất, tìm ra số tam giác lớn nhất T j đó là ít hơn n . Thì j là số nguyên áp chót được thêm vào trong bước 1 (vì sau khi thêm j + 1, chúng ta sẽ vượt quá n ). Sau đó phân tách n thành số nguyên liên tiếp (hoặc càng nhỏ) càng tốt và gọi cực đại trong số các số này k . Kết quả chỉ đơn giản là 2 * (kj) . Lý do trực quan cho điều này là vì tối đa trong phân tách tăng thêm 1 bước khác và chúng ta dừng lại khi đạt đượck .
Chúng ta cần chỉ ra bốn điều để chứng minh rằng điều này hoạt động:
- f (n) = 1 cho các số tam giác. Đây là trường hợp tầm thường, bởi vì bước đầu tiên chỉ đơn giản là lặp qua tất cả các số tam giác. Nếu chúng tôi đạt được n chính xác trong quá trình này, chúng tôi đã hoàn thành và chỉ có một bước để tính toán.
- Đối với tất cả các số khác, chúng tôi luôn kết thúc sau một bước xóa, không bao giờ sau bước chèn. Điều đó có nghĩa là tất cả các f (n) khác đều chẵn.
- Trong mỗi bước chèn sau bước đầu tiên, chúng tôi chỉ thêm một số duy nhất. Điều này đảm bảo rằng chúng ta sẽ đạt được phân tách bao gồm k sau các bước kj .
- Phân rã cuối cùng của n mà chúng ta thu được luôn là phân rã dài nhất có thể của n thành các số nguyên liên tiếp, hay nói cách khác, nó luôn luôn là phân rã của n với cực đại thấp nhất trong số các số tổng. Nói cách khác, số cuối cùng chúng ta thêm vào tổng luôn là A212652 (n) .
Chúng tôi đã chỉ ra tại sao (1) là đúng. Tiếp theo, chúng tôi chứng minh rằng chúng tôi không thể kết thúc ở bước chèn trừ bước đầu tiên (điều này không xảy ra đối với các số không phải là hình tam giác).
Giả sử chúng ta đã kết thúc ở bước chèn, đạt n sau khi thêm giá trị p vào tổng. Điều đó có nghĩa là trước bước chèn này, giá trị là np ( hoặc ít hơn nếu chúng ta thêm nhiều giá trị cùng một lúc). Nhưng bước chèn này được đi trước bởi một bước xóa (vì chúng ta không thể nhấn n trong bước 1). Giá trị cuối cùng q chúng tôi đã loại bỏ trong bước xóa này nhất thiết phải nhỏ hơn p do cách thức hoạt động của thuật toán. Nhưng điều đó có nghĩa là trước khi loại bỏ q, chúng ta có n-p + q ( hoặc ít hơn ) nhỏ hơn n. Nhưng đó là một mâu thuẫn, bởi vì chúng tôi sẽ phải ngừng xóa số nguyên khi chúng tôi nhấn n-p + q thay vì xóa q khác . Điều này chứng tỏ điểm (2) ở trên. Vì vậy, bây giờ chúng tôi biết rằng chúng tôi luôn kết thúc ở bước xóa và do đó tất cả các số không phải là tam giác đều có đầu ra.
Tiếp theo, chúng tôi chứng minh (3), rằng mỗi bước chèn chỉ có thể chèn một giá trị. Đây thực chất là một hệ quả của (2). Chúng tôi đã chỉ ra rằng sau khi thêm một giá trị, chúng tôi không thể đạt n chính xác và vì chứng minh đã sử dụng bất đẳng thức, chúng tôi cũng không thể kết thúc dưới n (kể từ đó n-p + q vẫn sẽ nhỏ hơn n và chúng tôi không nên xóa mà nhiều giá trị ở nơi đầu tiên). Vì vậy, bất cứ khi nào chúng tôi thêm một giá trị, chúng tôi đảm bảo vượt quá n vì chúng tôi đã xuống dưới n bằng cách xóa một giá trị nhỏ hơn. Do đó, chúng ta biết rằng đầu trên của tổng tăng thêm 1 mỗi bước khác. Chúng tôi biết giá trị ban đầu của phần trên này (nó là m nhỏ nhất sao choT m > n ). Bây giờ chúng ta chỉ cần tìm ra phần cuối này khi chúng ta đã đạt được số tiền cuối cùng. Sau đó, số lượng các bước chỉ đơn giản là gấp đôi sự khác biệt (cộng 1).
Để làm điều này, chúng tôi chứng minh (4), tổng cuối cùng luôn là phép phân tách n thành càng nhiều số nguyên càng tốt hoặc phân tách trong đó mức tối đa trong phân tách đó là tối thiểu (nghĩa là phân tách sớm nhất có thể). Một lần nữa chúng ta sẽ làm điều này bằng mâu thuẫn (từ ngữ trong phần này có thể khắt khe hơn một chút, nhưng tôi đã dành quá nhiều thời gian cho việc này ...).
Nói rằng sự phân tách sớm nhất / dài nhất có thể của n là một số a + (a + 1) + ... (b - 1) + b , a b và nói thuật toán bỏ qua nó. Điều đó có nghĩa là tại thời điểm b được thêm vào, a không còn là một phần của tổng. Nếu a là một phần của tổng s , thì chúng ta sẽ có n tại thời điểm đó. Vì vậy, tổng chỉ chứa các giá trị từ a đến b , bằng n và chúng ta dừng lại (do đó chúng ta không bỏ qua phép phân tách này) hoặc có ít nhất một giá trị nhỏ hơn a trong tổng, thắng trường hợp nào n <svà giá trị đó sẽ bị xóa cho đến khi chúng tôi đạt được tổng chính xác (một lần nữa, quá trình phân tách không bị bỏ qua). Vì vậy, chúng ta phải loại bỏ a trước khi thêm b . Nhưng điều đó có nghĩa là chúng ta sẽ phải đạt đến một tình huống trong đó a là thành phần nhỏ nhất của tổng và lớn nhất chưa phải là b . Tuy nhiên, tại thời điểm đó, chúng tôi không thể xóa a , vì tổng rõ ràng nhỏ hơn n (vì b bị thiếu), vì vậy chúng tôi bắt buộc phải thêm giá trị trước cho đến khi chúng tôi thêm b và nhấn n chính xác. Điều này chứng tỏ (4).
Vì vậy, kết hợp những điều này lại với nhau: chúng ta biết rằng cặp bước đầu tiên mang lại cho chúng ta giá trị tối đa là A002024 (n) . Chúng tôi biết rằng giá trị tối đa của phân tách cuối cùng là A212652 (n) . Và chúng tôi biết rằng mức tối đa này được tăng lên một lần trong mỗi cặp bước. Do đó, biểu thức cuối cùng là 2 * ( A212652 (n) - A002024 (n) + 1) . Công thức này hầu như hoạt động đối với các số tam giác, ngoại trừ với những người chúng ta chỉ cần 1 bước thay vì 2, đó là lý do tại sao chúng ta sửa kết quả với hàm chỉ thị của các số tam giác (hoặc nghịch đảo của nó, bất kỳ thuận tiện hơn).
Cuối cùng, như để thực hiện. Đối với chuỗi trước, tôi đang sử dụng công thức MIN (lẻ d | n; n / d + (d-1) / 2) từ OEIS. Hóa ra là tiết kiệm một vài byte nếu chúng ta lấy hệ số 2 vào biểu thức này để lấy MIN (lẻ d | n; 2n / d + d-1) , vì -1 đó sẽ hủy +1 trong phiên bản đầu tiên của tôi của f (n) mã hóa trực tiếp hai trường hợp cho số tam giác và không tam giác. Trong mã, đây là:
Min[2#/(d=Divisors@#~Cases~_?OddQ)+d]
Đối với chuỗi sau ( 1, 2, 2, 3, 3, 3, ...
), chúng ta có thể sử dụng một dạng đóng đơn giản:
⌊(2#)^.5+.5⌋
Và cuối cùng, hàm chỉ thị nghịch đảo của các số tam giác là 0 bất cứ khi nào 8n + 1 là một hình vuông hoàn hảo. Điều này có thể được thể hiện trong Mathicala như
⌈Sqrt[8#+1]~Mod~1⌉
Có rất nhiều cách để thể hiện hai chuỗi cuối cùng này và thay đổi một số bù trừ không đổi giữa chúng, vì vậy tôi chắc chắn đây chưa phải là một triển khai tối ưu, nhưng tôi hy vọng điều này có thể giúp người khác bắt đầu xem xét các cách tiếp cận mới trong ngôn ngữ riêng của họ.
Vì tôi đã đi đến tất cả những rắc rối này, đây là một chuỗi của chuỗi lên tới n = 1000 (tôi cũng có thể tính toán 100k trong vài giây, nhưng nó không thực sự hiển thị bất kỳ thông tin chi tiết bổ sung nào):
Có thể rất thú vị khi xem xét các biến thể về những đường thẳng đó, nhưng tôi sẽ để nó cho người khác ...