Số ký tự tối đa sử dụng tổ hợp phím A, Ctrl + A, Ctrl + C và Ctrl + V


106

Đây là một câu hỏi phỏng vấn từ google. Tôi không thể giải quyết nó một mình. Ai đó có thể làm sáng tỏ không?

Viết một chương trình để in chuỗi các tổ hợp phím sao cho nó tạo ra số ký tự 'A tối đa. Bạn được phép sử dụng chỉ có 4 phím: A, Ctrl+ A, Ctrl+ CCtrl+ V. Chỉ N tổ hợp phím được phép. Tất cả các Ctrlký tự + được coi là một lần nhấn phím, vì vậy Ctrl+ Alà một lần nhấn phím.

Ví dụ, chuỗi A, Ctrl+ A, Ctrl+ C, Ctrl+ Vtạo ra hai chữ A trong 4 lần nhấn phím.

  • Ctrl + A là Chọn tất cả
  • Ctrl + C là Sao chép
  • Ctrl + V là Dán

Tôi đã làm một số toán học. Với N bất kỳ, sử dụng x số A, một Ctrl+ A, một Ctrl+ Cvà y Ctrl+ V, chúng ta có thể tạo ra tối đa ((N-1) / 2) 2 số A. Đối với một số N> M, tốt hơn nên sử dụng càng nhiều dãy Ctrl+ A's, Ctrl+ CCtrl+ Vvì nó tăng gấp đôi số lượng A.

Chuỗi Ctrl+ A, Ctrl+ V, Ctrl+ Csẽ không ghi đè lựa chọn hiện có. Nó sẽ nối vùng chọn đã sao chép vào vùng đã chọn.


Trong nhiều trình soạn thảo văn bản ^Athường là "chọn tất cả", ^Clà "sao chép", ^Vlà "dán". Điều đó có cung cấp cho bạn một ý tưởng?
Nikolai Fetissov

Ý tôi là số 'A. Ví dụ, đối với N = 7 chúng ta có thể in 9 Một bằng cách sử dụng tổ hợp phím A, A, A, Ctrl + A, Ctrl + C, Ctrl + V, Ctrl + V
Munda

Uh, đó là 7 lần nhấn phím.
John Dibling

@John "Tất cả các ký tự CTRL + được coi là một lần nhấn phím, vì vậy CTRL + A là một lần nhấn phím."
fredley

1
Tôi đã xóa thẻ C ++, đây hoàn toàn là một câu hỏi thuật toán và hy vọng nó sẽ ngăn những người theo dõi c ++ không hài lòng phản đối / bỏ phiếu để đóng.
Matthieu M.

Câu trả lời:


43

Có một giải pháp lập trình động. Chúng ta bắt đầu biết 0 chìa khóa có thể làm cho chúng ta 0 A. Sau đó, chúng tôi lặp đi lặp lại cho iđến n, thực hiện hai việc: nhấn A một lần và nhấn chọn tất cả + sao chép, tiếp theo là dán jlần (thực tế là j-i-1bên dưới; lưu ý mẹo ở đây: nội dung vẫn còn trong khay nhớ tạm, vì vậy chúng tôi có thể dán nhiều lần mà không cần sao chép mỗi lần). Chúng ta chỉ phải xem xét tối đa 4 lần dán liên tiếp, vì chọn, sao chép, dán x 5 tương đương với chọn, sao chép, dán, chọn, sao chép, dán và cái sau tốt hơn vì nó để lại cho chúng ta nhiều hơn trong khay nhớ tạm. Khi chúng tôi đã đạt được n, chúng tôi có kết quả mong muốn.

Độ phức tạp có thể là O (N), nhưng vì các con số phát triển theo cấp số nhân nên nó thực sự là O (N 2 ) do sự phức tạp của việc nhân các số lớn. Dưới đây là một triển khai Python. Mất khoảng 0,5 giây để tính toán cho N = 50.000.

def max_chars(n):
  dp = [0] * (n+1)
  for i in xrange(n):
    dp[i+1] = max(dp[i+1], dp[i]+1) # press a
    for j in xrange(i+3, min(i+7, n+1)):
      dp[j] = max(dp[j], dp[i]*(j-i-1)) # press select all, copy, paste x (j-i-1)
  return dp[n]

Trong mã, jđại diện cho tổng số phím được nhấn sau chuỗi các lần nhấn phím mới của chúng tôi. Chúng tôi đã có các lần inhấn phím ở giai đoạn này, và 2 lần nhấn phím mới sẽ chuyển đến mục chọn-tất cả và sao chép. Do đó chúng tôi đang nhấn j-i-2thời gian dán . Vì việc dán sẽ thêm vào chuỗi hiện có của dp[i] A's, chúng ta cần thêm 1việc tạo nó j-i-1. Điều này giải thích j-i-1ở dòng thứ 2-cuối cùng.

Dưới đây là một số kết quả ( n=> số A):

  • 7 => 9
  • 8 => 12
  • 9 => 16
  • 10 => 20
  • 100 => 1391569403904
  • 1.000 => 3268160001953743683783272702066311903448533894049486008426303248121757146615064636953144900245 174442911064952028008546304
  • 50.000 => một con số rất lớn!

Tôi đồng ý với @SB rằng bạn nên luôn nêu rõ các giả định của mình: Của tôi là bạn không cần phải dán hai lần để tăng gấp đôi số ký tự. Điều này nhận được câu trả lời cho 7, vì vậy trừ khi giải pháp của tôi là sai, giả thiết phải đúng.

Trong trường hợp kỳ một người nào đó tại sao tôi không kiểm tra chuỗi có dạng Ctrl+ A, Ctrl+ C, A, Ctrl+ V: Kết quả cuối cùng sẽ luôn luôn giống như A, Ctrl+ A, Ctrl+ C, Ctrl+ Vmà tôi làm xét.


Đó là n => resulthoặc result => n? Dù thế nào thì tôi cũng nghĩ là sai. Chúng ta có thể gõ 9 Như với 7 tổ hợp phím. Nếu nó n => resultchắc chắn là sai. Số lượng Như bạn có thể nhập không được thấp hơn n.
IVlad

@IVlad Nó n => result. Bạn nói "Chúng ta có thể gõ 9 Như với 7 tổ hợp phím", đó là những gì tôi nhận được. Đọc "thủ thuật" tôi vừa chỉnh sửa.
moinudin

Điều này có vẻ tuyệt vời, ngoại trừ câu hỏi là tìm số lượng As tối đa cho một số lần gõ phím nhất định, chứ không phải số lần gõ phím tối thiểu để nhận được một số lượng As nhất định.
Andrew Clark

1
@marcog - ký hiệu của bạn ít gây nhầm lẫn và sai nhiều nhất. nlà tổ hợp phím bạn được phép sử dụng. Bạn phải tính có bao nhiêu Khi bạn có thể gõ bằng các ntổ hợp phím. Vì vậy, 7 => 7không có ý nghĩa.
IVlad

1
Có vẻ đúng, + 1. Bây giờ hãy xem liệu ai đó có thể lấy nó xuống O(n)hoặc thậm chí O(1):).
IVlad

41

Bằng cách sử dụng giải pháp của marcog, tôi đã tìm thấy một mô hình bắt đầu từ n=16. Để minh họa điều này, đây là các tổ hợp phím n=24lên đến n=29, tôi đã thay thế ^ A bằng S (chọn), ^ C bằng C (sao chép) và ^ V bằng P (dán) để dễ đọc:

24: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P
       4   *    4    *    4    *    4    *    4     = 1024
25: A,A,A,A,S,C,P,P,P,S,C,P,P,S,C,P,P,S,C,P,P,S,C,P,P
       4   *    4    *   3   *   3   *   3   *   3    = 1296
26: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,S,C,P,P,S,C,P,P
       4   *    4    *    4    *   3   *   3   *   3    = 1728
27: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,S,C,P,P
       4   *    4    *    4    *    4    *   3   *   3    = 2304
28: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P
       4   *    4    *    4    *    4    *    4    *   3    = 3072
29: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P
       4   *    4    *    4    *    4    *    4    *    4     = 4096

Sau 4 As ban đầu, mẫu lý tưởng là chọn, sao chép, dán, dán, dán và lặp lại. Điều này sẽ nhân số As với 4 sau mỗi 5 lần nhấn phím. Nếu 5 kiểu tổ hợp phím này không thể tự tiêu thụ các lần gõ phím còn lại thì một số trong 4 kiểu tổ hợp phím (SCPP) sẽ sử dụng các lần gõ phím cuối cùng, hãy thay thế SCPPP (hoặc xóa một trong các thao tác dán) nếu cần. 4 kiểu tổ hợp phím nhân tổng số với 3 sau mỗi 4 lần tổ chức phím.

Sử dụng mẫu này ở đây là một số mã Python nhận được kết quả giống như giải pháp của marcog, nhưng là O (1) chỉnh sửa : Đây thực sự là O (log n) do lũy thừa, cảm ơn IVlad đã chỉ ra điều đó.

def max_chars(n):
  if n <= 15:
    return (0, 1, 2, 3, 4, 5, 6, 9, 12, 16, 20, 27, 36, 48, 64, 81)[n]
  e3 = (4 - n) % 5
  e4 = n // 5 - e3
  return 4 * (4 ** e4) * (3 ** e3)

Tính e3: Luôn có từ 0 đến 4 mẫu SCPP ở cuối danh sách tổ hợp phím, vì n % 5 == 4có 4, n % 5 == 1có 3, n % 5 == 2có 2, n % 5 == 3có 1 và n % 5 == 4có 0. Điều này có thể được đơn giản hóa (4 - n) % 5.

Tính e4: Tổng số mẫu tăng lên 1 bất cứ khi nào n % 5 == 0, vì hóa ra số này tăng lên chính xác n / 5. Sử dụng phép chia tầng, chúng ta có thể nhận được tổng số mẫu, tổng số cho e4là tổng số mẫu trừ đi e3. Đối với những người không quen thuộc với Python, //là ký hiệu tương lai cho phép phân chia tầng.


1
Đẹp quá! Đã thử nghiệm và nó hoạt động n=3000, vì vậy nó có thể đúng. (Đáng tiếc, hôm nay tôi hết phiếu rồi: /)
moinudin

5
+1, rất tốt. Tuy nhiên, điều này không thực sự xảy ra O(1)vì không thể thực hiện phép tính lũy thừa trong thời gian liên tục. Nó O(log n).
IVlad

2
Trên thực tế, chuỗi 'SCPPP' sẽ chỉ nhân số ký tự với ba: lần dán đầu tiên chỉ cần ghi đè lên văn bản đã chọn.
Nick Johnson

4
@Nick Dòng cuối cùng trong câu hỏi: "Chuỗi Ctrl + A, Ctrl + V, Ctrl + C sẽ không ghi đè lựa chọn hiện có. Nó sẽ nối lựa chọn đã sao chép vào một lựa chọn đã chọn."
moinudin

2
@marcog Có, tôi không nhận thấy điều đó. Tuy nhiên, tôi không biết bất kỳ hệ điều hành nào hoạt động theo kiểu đó.
Nick Johnson

15

Đây là cách tôi sẽ tiếp cận nó:

  • giả sử CtrlA= chọn tất cả
  • giả sử CtrlC= sao chép lựa chọn
  • giả sử CtrlV= dán lựa chọn đã sao chép

cho một số văn bản, cần 4 lần nhấn phím để sao chép nó:

  • CtrlA để chọn tất cả
  • CtrlC sao chép nó
  • CtrlV để dán (điều này sẽ dán lên vùng lựa chọn - TIỂU BANG TIÊU BIỂU CỦA BẠN)
  • CtrlV để dán lại mà nhân đôi nó.

Từ đó, bạn có thể xem xét làm 4 hoặc 5 chữ A, sau đó lặp lại các bước trên. Lưu ý rằng làm như vậy ctrl + a, c, v, vsẽ phát triển văn bản của bạn theo cấp số nhân khi bạn lặp lại. Nếu số nét còn lại <4, chỉ cần tiếp tục thực hiệnCtrlV

Chìa khóa cho các cuộc phỏng vấn @ những nơi như Google là nêu các giả định của bạn và truyền đạt suy nghĩ của bạn. họ muốn biết cách bạn giải quyết vấn đề.


6
Điểm tốt về kỹ thuật phỏng vấn, nhận được câu trả lời chính xác ít quan trọng hơn là giao tiếp rõ ràng cuối cùng!
fredley

2
Câu trả lời tốt. Đối với các thuật toán, một tham lam off-by-hai lỗi: ACVV-VVVVVnhân lên 7, ACVV-ACVV-Vnhân lên bởi 6. Vì vậy, Ctrl-V cho đột quỵ còn lại <6 thay vì 4.
Marcel Jackwerth

5

Nó có thể giải được trong O (1): Giống như với các số Fibonacci, có một công thức để tính số As được in ra (và chuỗi các tổ hợp phím):


1) Chúng tôi có thể đơn giản hóa mô tả vấn đề:

  • Chỉ có [A], [Ca] + [Cc], [Cv] và một bộ đệm copy-paste-rỗng

bằng

  • chỉ có [Ca] + [Cc], [Cv] và "A" trong bộ đệm sao chép-dán.

2) Chúng ta có thể mô tả chuỗi các tổ hợp phím như một chuỗi N ký tự trong số {'*', 'V', 'v'}, trong đó 'v' có nghĩa là [Cv] và '*' có nghĩa là [Ca] và 'V 'có nghĩa là [Cc]. Ví dụ: "vvvv * Vvvvv * Vvvv"

Độ dài của sợi dây đó vẫn bằng N.

Tích độ dài của các từ Vv trong chuỗi đó bằng số As được tạo ra.


3) Với độ dài cố định N cho chuỗi đó và số từ cố định K, kết quả sẽ là tối đa khi tất cả các từ có độ dài gần bằng nhau. Chênh lệch giữa các cặp của chúng không quá ± 1.

Bây giờ, số tối ưu K, nếu N là bao nhiêu?


4) Giả sử, chúng ta muốn tăng số lượng từ bằng cách thêm một từ duy nhất có độ dài L, thì chúng ta phải giảm L + 1 lần bất kỳ từ nào trước đó đi một ký tự 'v'. Ví dụ: "… * Vvvv * Vvvv * Vvvv * Vvvv" -> "… * Vvv * Vvv * Vvv * Vvv * Vvv"

Bây giờ, độ dài từ tối ưu L là bao nhiêu?

(5 * 5 * 5 * 5 * 5) <(4 * 4 * 4 * 4 * 4) * 4, (4 * 4 * 4 * 4)> (3 * 3 * 3 * 3) * 3

=> Tối ưu là L = 4.


5) Giả sử, chúng ta có một N đủ lớn để tạo ra một chuỗi có nhiều từ có độ dài 4, nhưng còn lại một vài tổ hợp phím; chúng ta nên sử dụng chúng như thế nào?

  • Nếu còn lại 5 từ trở lên: Nối một từ khác có độ dài 4.

  • Nếu còn 0: Xong.

  • Nếu còn lại 4: Chúng tôi có thể

    a) Nối một từ có độ dài 3: 4 * 4 * 4 * 4 * 3 = 768.

    b) hoặc tăng 4 từ lên độ dài 5: 5 * 5 * 5 * 5 = 625. => Thêm một từ thì tốt hơn.

  • Nếu còn lại 3: Chúng tôi có thể

    a) hoặc nối một từ có độ dài 3 bằng cách điều chỉnh từ previus từ độ dài 4 thành 3: 4 * 4 * 4 * 2 = 128 <4 * 4 * 3 * 3 = 144.

    b) tăng 3 từ để có độ dài 5: 5 * 5 * 5 = 125. => Thêm một từ thì tốt hơn.

  • Nếu còn lại 2: Chúng tôi có thể

    a) hoặc nối một từ có độ dài 3 bằng cách điều chỉnh hai từ trước từ độ dài 4 thành 3: 4 * 4 * 1 = 16 <3 * 3 * 3 = 27.

    b) tăng 2 từ lên độ dài 5: 5 * 5 = 25. => Thêm một từ thì tốt hơn.

  • Nếu còn 1: Chúng tôi có thể

    a) hoặc nối một từ có độ dài 3 bằng cách điều chỉnh ba từ previus từ độ dài 4 thành 3: 4 * 4 * 4 * 0 = 0 <3 * 3 * 3 * 3 = 81.

    b) tăng một từ lên độ dài 5: 4 * 4 * 5 = 80. => Thêm một từ thì tốt hơn.


6) Bây giờ, điều gì sẽ xảy ra nếu chúng ta không có "N đủ lớn" để sử dụng các quy tắc trong 5)? Chúng ta phải tuân theo kế hoạch b), nếu có thể! Các chuỗi cho N nhỏ là:

1: "v", 2: "vv", 3: "vvv", 4: "vvvv"

5: "vvvvv" → 5 (kế hoạch b)

6: "vvvvvv" → 6 (kế hoạch b)

7: "vvv * Vvv" → 9 (phương án a)

8: "vvvv * Vvv" → 12 (kế hoạch a)

9: "vvvv * Vvvv" → 16

10: "vvvv * Vvvvv" → 20 (kế hoạch b)

11: "vvv * Vvv * Vvv" → 29 (kế hoạch a)

12: "vvvv * Vvv * Vvv" → 36 (kế hoạch a)

13: "vvvv * Vvvv * Vvv" → 48 (kế hoạch a)

14: "vvvv * Vvvv * Vvvv" → 64

15: "vvv * Vvv * Vvv * Vvv" → 81 (phương án a)


7) Bây giờ, số từ tối ưu K trong một chuỗi có độ dài N là bao nhiêu?

If N <7 then K = 1 else if 6 <N <11 then K = 2; ngược lại: K = ceil ((N + 1) / 5)

Được viết bằng C / C ++ / Java: int K = (N<7)?(1) : (N<11)?(2) : ((N+5)/5);

Và nếu N> 10, thì số từ có độ dài 3 sẽ là: K * 5-1-N. Với điều này, chúng tôi có thể tính toán số As được in:

Nếu N> 10, số As sẽ là: 4 ^ {N + 1-4K} · 3 ^ {5K-N-1}


Có vẻ đúng, phù hợp với các ví dụ được đưa ra bởi câu trả lời của @ Andrew, nhưng câu trả lời của bạn cũng là O (log N) thay vì O (1), phải không?
rsenna

Làm thế nào nó có thể là O (log N)? Công thức toán học để tính số As được tính trong O (1). Thuật toán in các tổ hợp phím là O (N) vì có O (N) tổ hợp phím để in hoặc O (1) iff bạn cho phép in dưới dạng biểu thức chính quy.
comonad

Tính lũy thừa là O (log N) vì số mũ trên 4 tăng với N. Nếu bạn in ra số As ở dạng thừa số thì nó là O (1).
Andrew Clark

À, được rồi. Chưa bao giờ nghĩ đến việc thực sự tính toán một số với số học nguyên. Tôi chỉ quan tâm đến công thức hoặc xấp xỉ dấu phẩy động. Nhưng tất nhiên, để có thể so sánh nó với những con số khác, nó sẽ phải được tính toán chính xác.
comonad

5

Sử dụng CtrlA+ CtrlC+ CtrlVlà một lợi thế chỉ sau 4 'A của.

Vì vậy, tôi sẽ làm một cái gì đó như thế này (trong mã giả CƠ BẢN, vì bạn chưa chỉ định bất kỳ ngôn ngữ thích hợp nào):

// We should not use the clipboard for the first four A's:
FOR I IN 1 TO MIN(N, 4)
    PRINT 'CLICK A'
NEXT
LET N1 = N - 4

// Generates the maximum number of pastes allowed:
FOR I IN 1 TO (N1 DIV 3) DO
    PRINT 'CTRL-A'
    PRINT 'CTRL-C'
    PRINT 'CTRL-V'
    LET N1 = N1 - 3
NEXT

// If we still have same keystrokes left, let's use them with simple CTRL-Vs
FOR I IN N1 TO N
    PRINT 'CTRL-V'
NEXT

Biên tập

  1. Quay lại việc sử dụng một đơn CtrlVtrong vòng lặp chính.
  2. Đã thêm một số nhận xét để giải thích những gì tôi đang cố gắng làm ở đây.
  3. Đã khắc phục sự cố với khối "bốn chữ A đầu tiên".

@SB: Tôi đang thực hiện CTRL-V chỉ cho các lần dán CUỐI CÙNG . Nhân tiện, đó là chính xác những gì bạn đã nói trong câu trả lời của mình. Có nghĩa là chúng tôi nghĩ tương tự, vì vậy tôi không biết tại sao bạn lại chỉ trích tôi - hoặc có thể tôi đang thiếu điều gì đó?
rsenna

1
google không bao giờ chỉ định một ngôn ngữ thích hợp để viết, mà bạn muốn.
Spooks

3

Cần 3 lần nhấn phím để nhân đôi số As của bạn. Việc bắt đầu nhân đôi chỉ có ý nghĩa khi bạn có 3 hoặc nhiều hơn Như đã được in. Bạn muốn tổ hợp phím được phép cuối cùng của mình là a CtrlVđể đảm bảo bạn đang tăng gấp đôi số lớn nhất có thể, vì vậy để căn chỉnh nó, chúng tôi sẽ điền vào bất kỳ tổ hợp phím nào sau ba phím As đầu tiên với nhiều As hơn.

for (i = 3 + n%3; i>0 && n>0; n--, i--) {
    print("a");
}

for (; n>0; n = n-3) {
    print("ctrl-a");
    print("ctrl-c");
    print("ctrl-v");
}

Biên tập:

Điều này thật khủng khiếp, tôi đã hoàn toàn vượt lên chính mình và không cân nhắc nhiều loại bột nhão cho mỗi bản sao.

Chỉnh sửa 2:

Tôi tin rằng dán 3 lần là tối ưu, khi bạn có đủ số lần nhấn phím để thực hiện. Trong 5 lần nhấn phím, bạn nhân số As của mình với 4. Điều này tốt hơn nhân với 3 bằng 4 lần nhấn phím và tốt hơn nhân với 5 bằng 6 lần nhấn phím. Tôi đã so sánh điều này bằng cách cho mỗi phương pháp cùng một số lần nhấn phím, đủ để chúng kết thúc một chu kỳ cùng một lúc (60), cho phép hệ số 3 thực hiện 15 chu kỳ, hệ số 4 thực hiện 12 chu kỳ và hệ số 5 nhân làm 10 chu kỳ. 3 ^ 15 = 14,348,907, 4 ^ 12 = 16,777,216 và 5 ^ 10 = 9,765,625. Nếu chỉ còn 4 lần nhấn phím, thực hiện phép nhân 3 sẽ tốt hơn là dán thêm 4 lần nữa, về cơ bản làm cho số nhân 4 trước đó trở thành cấp số nhân 8. Nếu chỉ còn 3 lần nhấn phím, tốt nhất là hệ số 2.


2

Giả sử bạn có x ký tự trong clipboard và x ký tự trong vùng văn bản; chúng ta hãy gọi nó là "trạng thái x".

Hãy nhấn "Dán" một vài lần (tôi ký hiệu là m-1để thuận tiện), sau đó "Chọn tất cả" và "Sao chép"; sau chuỗi này, chúng ta đến "trạng thái m * x". Ở đây, chúng tôi đã lãng phí tổng cộng m + 1 lần nhấn phím. Vì vậy, tăng trưởng tiệm cận là (ít nhất) một cái gì đó giống như f^n, trong đó f = m^(1/(m+1)). Tôi tin rằng đó là mức tăng trưởng tiệm cận tối đa có thể, mặc dù tôi chưa thể chứng minh (chưa).

Thử các giá trị khác nhau của m cho thấy rằng giá trị lớn nhất của f đạt được m=4.

Hãy sử dụng thuật toán sau:

Press A a few times
Press Select-all
Press Copy
Repeat a few times:
    Press Paste
    Press Paste
    Press Paste
    Press Select-all
    Press Copy
While any keystrokes left:
    Press Paste

(không chắc đó là cái tối ưu).

Số lần nhấn phím A lúc đầu là 3: nếu nhấn 4 lần, bạn bỏ lỡ cơ hội nhân đôi số chữ A trong 3 lần nhấn phím nữa.

Số lần nhấn Paste khi kết thúc không quá 5 lần: nếu bạn còn lại 6 tổ hợp phím trở lên, bạn có thể sử dụng Paste, Paste, Paste, Select-all, Copy, Paste để thay thế.

Vì vậy, chúng tôi nhận được thuật toán sau:

If (less than 6 keystrokes - special case)
    While (any keystrokes left)
        A
Else
    First 5 keystrokes: A, A, A, Select-all, Copy
    While (more than 5 keystrokes left)
        Paste, Paste, Paste, Select-all, Copy
    While (any keystrokes left)
        Paste

(không chắc đó là cái tối ưu). Số lượng ký tự sau khi thực hiện điều này giống như

3 * pow(4, floor((n - 6) / 5)) * (2 + (n - 1) % 5).

Giá trị mẫu: 1,2,3,4,5,6,9,12,15,18,24,36,48,60,72,96,144,192,240,288, ...


2

Những gì tiếp theo sử dụng chỉnh sửa thứ hai của OP mà việc dán không thay thế văn bản hiện có.

Lưu ý một số điều:

  • ^ A và ^ C có thể được coi là một hành động đơn lẻ thực hiện hai lần nhấn phím, vì không bao giờ có ý nghĩa nếu thực hiện chúng một cách riêng lẻ. Trên thực tế, chúng ta có thể thay thế tất cả các trường hợp của ^ A ^ C bằng ^ K ^ V, trong đó ^ K là phép toán "cắt" một phím (hãy viết tắt nó là X). Chúng ta sẽ thấy rằng xử lý ^ K tốt hơn nhiều so với ^ A ^ C hai chi phí.
  • Giả sử rằng chữ 'A' bắt đầu trong khay nhớ tạm. Khi đó ^ V (hãy viết tắt nó là Y) hoàn toàn vượt trội so với A và chúng ta có thể loại bỏ điều sau khỏi tất cả các xem xét. (Trong vấn đề thực tế, nếu khay nhớ tạm bắt đầu trống, trong những gì tiếp theo, chúng tôi sẽ chỉ thay thế Y bằng A thay vì ^ V cho đến X đầu tiên)

Do đó, mọi chuỗi tổ hợp phím hợp lý có thể được hiểu là một nhóm Y được phân tách bằng X, ví dụ YYYXYXYYXY. Ký hiệu bằng V (các) số 'A được tạo ra bởi dãy s. Khi đó V (nXm) = V (n) * V (m), vì X về cơ bản thay thế mọi Y trong m bằng V (n) 'A.

Do đó, bài toán sao chép-dán là đồng dạng với bài toán sau: "sử dụng m + 1 số tổng bằng Nm, tối đa hóa tích của chúng." Ví dụ, khi N = 6, câu trả lời là m = 1 và các số (2,3). 6 = 2 * 3 = V (YYXYYY) = V (AA ^ A ^ C ^ V ^ V) (hoặc V (YYYXYY) = V (AAA ^ A ^ C ^ V).)

Chúng ta có thể thực hiện một vài nhận xét:

Đối với một giá trị cố định của m, các số để chọn là ceil( (N-m)/(m+1) )floor( (N-m)/(m+1) )(trong bất kỳ sự kết hợp nào làm cho tổng có hiệu quả; cụ thể hơn bạn sẽ cần (N-m) % (m+1) ceilsvà các số còn lại floor). Điều này là do, cho a < b, (a+1)*(b-1) >= a*b.

Thật không may, tôi không thấy một cách dễ dàng để tìm thấy giá trị của m. Nếu đây là cuộc phỏng vấn của tôi, tôi sẽ đề xuất hai giải pháp tại thời điểm này:

Tùy chọn 1. Lặp lại tất cả có thể m. Một n log ndung dịch O ( ).

Mã C ++:

long long ipow(int a, int b)
{
  long long val=1;
  long long mul=a;

  while(b>0)
    {
      if(b%2)
    val *= mul;
      mul *= mul;
      b/=2;
    }
  return val;
}

long long trym(int N, int m)
{
  int floor = (N-m)/(m+1);
  int ceil = 1+floor;
  int numceils = (N-m)%(m+1);
  return ipow(floor, m+1-numceils) * ipow(ceil, numceils);
}

long long maxAs(int N)
{
  long long maxval=0;
  for(int m=0; m<N; m++)
    {
      maxval = std::max(maxval, trym(N,m));
    }
  return maxval;
}

Phương án 2. Cho phép mđạt được các giá trị không nguyên và tìm giá trị tối ưu của nó bằng cách lấy đạo hàm [(N-m)/(m+1)]^mđối với mvà giải cho căn của nó. Không có giải pháp phân tích, nhưng gốc có thể được tìm thấy bằng cách sử dụng phương pháp Newton. Sau đó, sử dụng sàn và trần của gốc đó cho giá trị mvà chọn cái nào tốt nhất.


0
public int dp(int n) 
{
    int arr[] = new int[n];
    for (int i = 0; i < n; i++)
        arr[i] = i + 1;
    for (int i = 2; i < n - 3; i++) 
    {
        int numchars = arr[i] * 2;
        int j = i + 3;
        arr[j] = Math.max(arr[j], numchars);
        while (j < n - 1) 
        {
            numchars = numchars + arr[i];
            arr[++j] = Math.max(arr[j], numchars);
        }
    }
    return arr[n - 1];
}

0

Đây là cách tiếp cận và giải pháp của tôi với đoạn mã dưới đây.

Tiếp cận:

Có ba hoạt động riêng biệt có thể được thực hiện.

  1. Tổ hợp phím A - Xuất ra một ký tự 'A'
  2. Tổ hợp phím (Ctrl-A) + (Ctrl-C) - Về cơ bản không xuất ra. Hai tổ hợp phím này có thể được kết hợp thành một thao tác vì mỗi tổ hợp phím riêng lẻ không có ý nghĩa gì. Ngoài ra, tổ hợp phím này thiết lập đầu ra cho thao tác dán tiếp theo.
  3. Tổ hợp phím (Ctrl-V) - Đầu ra cho tổ hợp phím này thực sự phụ thuộc vào thao tác trước đó (thứ hai) và do đó chúng ta cần tính đến thao tác đó trong mã của mình.

Bây giờ với ba phép toán riêng biệt và kết quả đầu ra tương ứng của chúng, chúng ta phải chạy qua tất cả các hoán vị của các phép toán này.


Giả thiết:

Bây giờ, một số phiên bản của sự cố này nói rằng chuỗi các tổ hợp phím, Ctrl + A -> Ctrl + C -> Ctrl + V, sẽ ghi đè lựa chọn được đánh dấu. Để đạt được giả định này, chỉ cần thêm một dòng mã vào giải pháp bên dưới, trong đó biến in trong trường hợp 2 được đặt thành 0

        case 2:
        //Ctrl-A and then Ctrl-C
            if((count+2) < maxKeys)
            {
                pOutput = printed;

                //comment the below statement to NOT factor 
                //in the assumption described above
                printed = 0;    
            }

Đối với giải pháp này

Đoạn mã dưới đây sẽ in ra một vài dãy và dãy cuối cùng là câu trả lời đúng cho bất kỳ N. nào cho trước, ví dụ N = 11 thì đây sẽ là dãy đúng

Với giả định

A, A, A, A, A, C, S, V, V, V, V,: 20:

Không có giả định

A, A, A, C, S, V, V, C, S, V, V,: 27:

Tôi đã quyết định giữ lại giả định cho giải pháp này.


Chú giải tổ hợp phím:

'A' - A

'C' - Ctrl + A

'S' - Ctrl + C

'V' - Ctrl + V


Mã:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void maxAprinted(int count, int maxKeys, int op, int printed, int pOutput, int *maxPrinted, char *seqArray)
{
    if(count > maxKeys)
        return;

    if(count == maxKeys)
    {
        if((*maxPrinted) < printed)
        {
            //new sequence found which is an improvement over last sequence
            (*maxPrinted) = printed;

            printf("\n");
            int i;
            for(i=0; i<maxKeys; i++)
                printf(" %c,",seqArray[i]);
        }

        return;
    }

    switch(op)
    {
        case 1:
        //A keystroke
            printed++;

            seqArray[count] = 'A';
            count++;
            break;

        case 2:
        //Ctrl-A and then Ctrl-C
            if((count+2) < maxKeys)
            {
                pOutput = printed;

                //comment the below statement to NOT factor 
                //in the assumption described above
                printed = 0;    
            }

            seqArray[count] = 'C';
            count++;
            seqArray[count] = 'S';
            count++;
            break;

        case 3:
        //Ctrl-V
            printed = printed + pOutput;

            seqArray[count] = 'V';
            count++;
            break;
    }

    maxAprinted(count, maxKeys, 1, printed, pOutput, maxPrinted, seqArray);
    maxAprinted(count, maxKeys, 2, printed, pOutput, maxPrinted, seqArray);
    maxAprinted(count, maxKeys, 3, printed, pOutput, maxPrinted, seqArray);    
}

int main()
{
    const int keyStrokes = 11;

    //this array stores the sequence of keystrokes
    char *sequence;
    sequence = (char*)malloc(sizeof(char)*(keyStrokes + 1));

    //stores the max count for As printed for a sqeuence
    //updated in the recursive call.
    int printedAs = 0;

    maxAprinted(0, keyStrokes,  1, 0, 0, &printedAs, sequence);

    printf(" :%d:", printedAs);

    return 0;
}    

0

Sử dụng các thủ thuật được đề cập trong các câu trả lời ở trên, về mặt toán học, Lời giải có thể được giải thích trong một phương trình là,

4 + 4 ^ [(N-4) / 5] + ((N-4)% 5) * 4 ^ [(N-4) / 5]. trong đó [] là hệ số nguyên lớn nhất


0

Có sự cân bằng giữa việc in mA theo cách thủ công, sau đó sử dụng Ctrl+ A, Ctrl+ Cvà Nm-2 Ctrl+ V. Giải pháp tốt nhất là ở giữa. Nếu số lần gõ phím tối đa = 10, giải pháp tốt nhất là gõ 5 chữ A hoặc 4 chữ A.

hãy thử sử dụng cái này. Hãy xem http://www.geeksforgeeks.org/how-to-print-maximum-number-of-a-using-given-four-keys/ và có thể tối ưu hóa một chút để tìm kiếm kết quả ở giữa điểm.


0

Đây là giải pháp của tôi với lập trình động, không có vòng lặp lồng nhau và cũng in ra các ký tự thực mà bạn cần nhập:

N = 52

count = [0] * N
res = [[]] * N
clipboard = [0] * N

def maybe_update(i, new_count, new_res, new_clipboard):
  if new_count > count[i] or (
      new_count == count[i] and new_clipboard > clipboard[i]):
    count[i] = new_count
    res[i] = new_res
    clipboard[i] = new_clipboard

for i in range(1, N):
  # First option: type 'A'.
  # Using list concatenation for 'res' to avoid O(n^2) string concatenation.
  maybe_update(i, count[i - 1] + 1, res[i - 1] + ['A'], clipboard[i - 1])

  # Second option: type 'CTRL+V'.
  maybe_update(i, count[i - 1] + clipboard[i - 1],  res[i - 1] + ['v'],
               clipboard[i - 1])

  # Third option: type 'CTRL+A, CTRL+C, CTRL+V'.
  # Assumption: CTRL+V always appends.
  if i >= 3:
    maybe_update(i, 2 * count[i - 3],  res[i - 3] + ['acv'], count[i - 3])

for i in range(N):
  print '%2d %7d %6d %-52s' % (i, count[i], clipboard[i], ''.join(res[i]))

Đây là đầu ra ('a' có nghĩa là 'CTRL + A', v.v.)

 0       0      0                                                     
 1       1      0 A                                                   
 2       2      0 AA                                                  
 3       3      0 AAA                                                 
 4       4      0 AAAA                                                
 5       5      0 AAAAA                                               
 6       6      3 AAAacv                                              
 7       9      3 AAAacvv                                             
 8      12      3 AAAacvvv                                            
 9      15      3 AAAacvvvv                                           
10      18      9 AAAacvvacv                                          
11      27      9 AAAacvvacvv                                         
12      36      9 AAAacvvacvvv                                        
13      45      9 AAAacvvacvvvv                                       
14      54     27 AAAacvvacvvacv                                      
15      81     27 AAAacvvacvvacvv                                     
16     108     27 AAAacvvacvvacvvv                                    
17     135     27 AAAacvvacvvacvvvv                                   
18     162     81 AAAacvvacvvacvvacv                                  
19     243     81 AAAacvvacvvacvvacvv                                 
20     324     81 AAAacvvacvvacvvacvvv                                
21     405     81 AAAacvvacvvacvvacvvvv                               
22     486    243 AAAacvvacvvacvvacvvacv                              
23     729    243 AAAacvvacvvacvvacvvacvv                             
24     972    243 AAAacvvacvvacvvacvvacvvv                            
25    1215    243 AAAacvvacvvacvvacvvacvvvv                           
26    1458    729 AAAacvvacvvacvvacvvacvvacv                          
27    2187    729 AAAacvvacvvacvvacvvacvvacvv                         
28    2916    729 AAAacvvacvvacvvacvvacvvacvvv                        
29    3645    729 AAAacvvacvvacvvacvvacvvacvvvv                       
30    4374   2187 AAAacvvacvvacvvacvvacvvacvvacv                      
31    6561   2187 AAAacvvacvvacvvacvvacvvacvvacvv                     
32    8748   2187 AAAacvvacvvacvvacvvacvvacvvacvvv                    
33   10935   2187 AAAacvvacvvacvvacvvacvvacvvacvvvv                   
34   13122   6561 AAAacvvacvvacvvacvvacvvacvvacvvacv                  
35   19683   6561 AAAacvvacvvacvvacvvacvvacvvacvvacvv                 
36   26244   6561 AAAacvvacvvacvvacvvacvvacvvacvvacvvv                
37   32805   6561 AAAacvvacvvacvvacvvacvvacvvacvvacvvvv               
38   39366  19683 AAAacvvacvvacvvacvvacvvacvvacvvacvvacv              
39   59049  19683 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvv             
40   78732  19683 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvv            
41   98415  19683 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvvv           
42  118098  59049 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacv          
43  177147  59049 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvv         
44  236196  59049 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvv        
45  295245  59049 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvvv       
46  354294 177147 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacv      
47  531441 177147 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvv     
48  708588 177147 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvv    
49  885735 177147 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvvv   
50 1062882 531441 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacv  
51 1594323 531441 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvv 

0

Nếu N lần nhấn phím được cho phép, thì kết quả là N-3.

A -> N-3

CTRL+A -> Chọn N ký tự đó: +1

CTRL+ C-> Sao chép N ký tự đó: +1

Ctrl+ V-> Dán N ký tự. : +1 tức là, (Vì chúng tôi đã chọn toàn bộ ký tự bằng CTRL+ A) Thay thế N-3 ký tự hiện có này bằng N-3 ký tự đã sao chép (đang ghi đè các ký tự giống nhau) và kết quả là N-3.


Chào mừng bạn đến với StackOverflow! Tìm hiểu cách thêm định dạng nội dung và có thể sử dụng biểu tượng mũi tên thực tế . Điều này sẽ cải thiện khả năng đọc câu trả lời của bạn!
M. Mimpen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.