Максимальное количество символов с помощью клавиш A, Ctrl + A, Ctrl + C и Ctrl + V
Это вопрос интервью из Google. Я не могу решить это сам. Может кто-то пролил свет?
Напишите программу для печати последовательности нажатий клавиш так, чтобы она генерировала максимальное количество символов "A". Вам разрешено использовать только 4 клавиши: A, Ctrl + A, Ctrl + C и Ctrl + V. Разрешены только N нажатий клавиш. Все символы Ctrl + считаются одним нажатием клавиши, поэтому Ctrl + A является одним нажатием клавиши.
Например, последовательность A, Ctrl + A, Ctrl + C, Ctrl + V генерирует два A в 4 нажатиях клавиш.
- Ctrl + A - Выбрать все
- Ctrl + C - копирование
- Ctrl + V - Вставить
Я сделал некоторую математику. Для любого N, используя x чисел A, один Ctrl + A, один Ctrl + C и y Ctrl + V, мы можем создать max ((N-1)/2) 2 количество A. Для некоторого N > M лучше использовать столько последовательностей Ctrl + A, Ctrl + C и Ctrl + V, сколько удваивает число A.
Последовательность Ctrl + A, Ctrl + V, Ctrl + C не перезапишет существующий выбор. Он добавит скопированный выбор к выбранному.
Ответы
Ответ 1
Там есть динамическое программирующее решение. Мы начинаем знать, что 0 клавиш могут сделать нас 0 A. Затем мы перебираем для i
до n
, делая две вещи: нажимая A один раз и нажимая select all + copy, а затем вставьте j
times (на самом деле j-i-1
ниже), обратите внимание на трюк здесь: содержимое все еще в буфер обмена, чтобы мы могли вставлять его несколько раз без копирования каждый раз). Нам нужно рассмотреть только до четырех последовательных паст, поскольку выбор, копирование, вставка x 5 эквивалентно выбору, копированию, вставке, выбору, копированию, вставке, а последнее лучше, так как оно оставляет нам больше в буфере обмена. Как только мы достигнем n
, мы получим желаемый результат.
Сложность может показаться O (N), но поскольку числа растут с экспоненциальной скоростью, это фактически O (N 2) из-за сложности умножения больших чисел. Ниже приведена реализация Python. Для вычисления N = 50 000 требуется около 0,5 секунды.
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]
В коде j
отображается общее количество нажатых клавиш после нашей новой последовательности нажатий клавиш. На этом этапе у нас уже есть клавиши i
, а 2 новых нажатия клавиш - для выбора и копирования. Поэтому мы нажимаем пасту j-i-2
раз. Поскольку вставка добавляет к существующей последовательности dp[i]
A
's, нам нужно добавить 1
, сделав ее j-i-1
. Это объясняет j-i-1
во второй строке.
Вот некоторые результаты (n
= > число A):
- 7 = > 9
- 8 = > 12
- 9 = > 16
- 10 = > 20
- 100 = > 1391569403904
- 1,000 = > 3268160001953743683783272702066311903448533894049486008426303248121757146615064636953144900245
174442911064952028008546304
- 50,000 = > очень большое число!
Я согласен с @SB, что вы всегда должны указывать свои предположения: Mine заключается в том, что вам не нужно вставлять дважды, чтобы удвоить количество символов. Это получает ответ за 7, поэтому, если мое решение не так, предположение должно быть правильным.
Если кто-то задается вопросом, почему я не проверяю последовательности формы Ctrl + A, Ctrl + C, A, Ctrl + V: конечный результат всегда будет быть таким же, как A, Ctrl + A, Ctrl + C, Ctrl + V, который я считаю.
Ответ 2
Используя решение marcog, я нашел шаблон, начинающийся с n=16
. Чтобы проиллюстрировать это, это клавиши для n=24
до n=29
, я заменил ^ A на S (select), ^ C с C (копией) и ^ V с P (paste) для удобочитаемости:
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
После первоначального 4 As идеальный паттерн - выбирать, копировать, вставлять, вставлять, вставлять и повторять. Это умножит число As на 4 каждые 5 нажатий клавиш. Если этот 5-тикратный шаблон не может использовать оставшиеся нажатия клавиш, некоторые из четырех комбинаций клавиш (SCPP) потребляют окончательные нажатия клавиш, заменяя SCPPP (или удаляя один из пасты) по мере необходимости. 4 рисунка нажатия клавиши умножают общее на 3 каждые 4 нажатия клавиш.
Использование этого шаблона здесь - это некоторый код Python, который получает те же результаты, что и решение marcog, но является O (1) edit. Это фактически O (log n) из-за возведения в степень, благодаря IVlad для указания этого.
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)
Вычисление e3:
В конце списка нажатия клавиш всегда есть от 0 до 4 SCPP, для n % 5 == 4
- 4, n % 5 == 1
- 3, n % 5 == 2
- 2, n % 5 == 3
- 1 и n % 5 == 4
есть 0. Это можно упростить до (4 - n) % 5
.
Вычисление e4:
Общее число шаблонов увеличивается на 1 при n % 5 == 0
, так как оказывается, что это число возрастает до точности n / 5
. Используя разделение по полу, мы можем получить общее количество шаблонов, общее число для e4
- общее количество шаблонов минус e3
. Для тех, кто не знаком с Python, //
- это будущая нотация для разделения полов.
Ответ 3
Вот как я подойду к нему:
- предположим Ctrl A= выбрать все
- предположим Ctrl C= выбор копии
- предположим Ctrl V= скопировать выделенную копию
с учетом некоторого текста, для его дублирования требуется 4 нажатия клавиш:
- Ctrl A, чтобы выбрать все
- Ctrl C, чтобы скопировать его
- Ctrl V для вставки (это будет вставляться над выбором - СОСТОЯНИЕ ВАШИХ ПРЕДПОЛОЖЕНИЙ)
- Ctrl V, чтобы снова вставить его, что удваивает его.
Оттуда вы можете рассмотреть возможность выполнения 4 или 5 A, а затем выполнить цикл выше. Обратите внимание, что выполнение ctrl + a, c, v, v
будет увеличивать ваш текст экспоненциально по мере прохождения цикла. Если оставшиеся штрихи < 4, просто продолжайте делать Ctrl V
Ключ к интервью @таким местам, как Google, заключается в том, чтобы изложить свои предположения и сообщить свое мышление. они хотят знать, как вы решаете проблемы.
Ответ 4
Использование Ctrl A + Ctrl C + Ctrl V является преимуществом только после 4 'А.
Итак, я бы сделал что-то вроде этого (в псевдо-BASIC-коде, так как вы не указали какой-либо правильный язык):
// 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 use them with simple CTRL-Vs
FOR I IN N1 TO N
PRINT 'CTRL-V'
NEXT
Edit
- Вернемся к использованию одного Ctrl V в основном цикле.
- Добавлены комментарии для объяснения того, что я пытаюсь сделать здесь.
- Исправлена проблема с блоком "первые четыре A".
Ответ 5
Он доступен для решения в O (1): как и числа Фибоначчи, существует формула для вычисления количества печатных As (и последовательности нажатий клавиш):
1) Мы можем упростить описание проблемы:
- Имея только [A], [C-a] + [C-c], [C-v] и пустой буфер копирования-вставки
равно
- имеющий только [C-a] + [C-c], [C-v] и "A" в буфере copy-paste.
2) Мы можем описать последовательность нажатий клавиш как строку из N символов из {'*', 'V', 'v'}, где 'v' означает [Cv], а '*' означает [Ca] и 'V' означает [Cc]. Пример: "vvvv * Vvvvv * Vvvv"
Длина этой строки по-прежнему равна N.
Произведение длин Vv-слов в этой строке равно числу выпущенных As.
3) Учитывая фиксированную длину N для этой строки и фиксированное число K слов, результат будет максимальным, если все слова имеют почти равную длину. Их различие в паре не более ± 1.
Теперь, каково оптимальное число K, если N задано?
4) Предположим, мы хотим увеличить число слов, добавив одно слово длины L, тогда мы должны уменьшить L + 1 раз любое предыдущее слово на один 'v'. Пример: "... * Vvvv * Vvvv * Vvvv * Vvvv" → "... * Vvv * Vvv * Vvv * Vvv * Vvv"
Теперь, какова оптимальная длина слова L?
(5 * 5 * 5 * 5 * 5) (4 * 4 * 4 * 4 * 4) * 4, (4 * 4 * 4 * 4) > (3 * 3 * 3 * 3) * 3
= > Оптимальное значение L = 4.
5) Предположим, что у нас достаточно большого N для генерации строки со многими словами длиной 4, но осталось несколько нажатий клавиш; как их использовать?
-
Если осталось 5 или более левых: добавьте другое слово длиной 4.
-
Если осталось 0: Готово.
-
Если осталось 4: мы можем либо
a) добавьте одно слово длиной 3: 4 * 4 * 4 * 4 * 3 = 768.
b) или увеличить 4 слова до длины 5: 5 * 5 * 5 * 5 = 625. = > Добавление одного слова лучше.
-
Если осталось 3: мы можем либо
a) или добавьте одно слово длиной 3, отрегулировав слово previus от длины 4 до 3: 4 * 4 * 4 * 2 = 128 < 4 * 4 * 3 * 3 = 144.
b) увеличить 3 слова до длины 5: 5 * 5 * 5 = 125. = > Добавление одного слова лучше.
-
Если осталось 2: мы можем либо
a) или добавьте одно слово длиной 3, отрегулировав два слова предыдущего с длиной от 4 до 3: 4 * 4 * 1 = 16 < 3 * 3 * 3 = 27.
b) увеличить 2 слова до длины 5: 5 * 5 = 25. = > Добавление одного слова лучше.
-
Если осталось 1: мы можем либо
a) или добавьте одно слово длиной 3, отрегулировав три слова трижды от длины 4 до 3: 4 * 4 * 4 * 0 = 0 < 3 * 3 * 3 * 3 = 81.
b) увеличить одно слово до длины 5: 4 * 4 * 5 = 80. = > Добавление одного слова лучше.
6) Итак, что, если у нас нет "достаточного большого N" для использования правил в 5)? Мы должны придерживаться плана б), если это возможно!
Строки для малых N:
1: "v", 2: "vv", 3: "vvv", 4: "vvvv"
5: "vvvvv" → 5 (план b)
6: "vvvvvv" → 6 (план b)
7: "vvv * Vvv" → 9 (план a)
8: "vvvv * Vvv" → 12 (план a)
9: "vvvv * Vvvv" → 16
10: "vvvv * Vvvvv" → 20 (план b)
11: "vvv * Vvv * Vvv" → 29 (план a)
12: "vvvv * Vvv * Vvv" → 36 (план a)
13: "vvvv * Vvvv * Vvv" → 48 (план a)
14: "vvvv * Vvvv * Vvvv" → 64
15: "vvv * Vvv * Vvv * Vvv" → 81 (план a)
...
7) Теперь, каково оптимальное число K слов в строке длины N?
Если N < 7, тогда K = 1 else, если 6 < N < 11, то K = 2; в противном случае: K = ceil ((N + 1)/5)
Написан на языке C/С++/Java: int K = (N<7)?(1) : (N<11)?(2) : ((N+5)/5);
И если N > 10, то число слов с длиной 3 будет: K * 5-1-N. При этом мы можем вычислить количество напечатанных As:
Если N > 10, число As будет: 4 ^ {N + 1-4K} · 3 ^ {5K-N-1}
Ответ 6
Требуется 3 нажатия клавиш, чтобы удвоить количество символов As. Имеет смысл начать удвоение, если у вас есть 3 или более Как уже напечатано. Вы хотите, чтобы ваше последнее нажатие клавиши было Ctrl V, чтобы убедиться, что вы удваиваете наибольшее количество, которое вы можете, поэтому, чтобы выровнять его, мы наполним любые дополнительные нажатия клавиш после первых трех. Как в начале с более В виде.
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");
}
Edit:
Это ужасно, я полностью опередил себя и не рассматривал несколько паст для каждой копии.
Изменить 2:
Я считаю, что вставка 3 раза оптимальна, когда у вас достаточно нажатий клавиш, чтобы сделать это. В 5 нажатиях клавиш вы умножаете свой номер As на 4. Это лучше, чем умножение на 3 с использованием 4 нажатий клавиш и лучше, чем умножение на 5 с использованием 6 нажатий клавиш. Я сравнивал это, предоставляя каждому методу такое же количество нажатий клавиш, что и каждый из них заканчивал цикл одновременно (60), позволяя 3-мультипликатору делать 15 циклов, 4-множитель делает 12 циклов, а 5- множитель выполняет 10 циклов. 3 ^ 15 = 14,348,907, 4 ^ 12 = 16,777,216 и 5 ^ 10 = 9,765,625. Если осталось всего 4 нажатия клавиш, выполнение 3-множителя лучше, чем склеивание еще 4 раза, по сути дела, что предыдущий 4-множитель станет 8-множителем. Если осталось всего 3 нажатия клавиш, лучше всего использовать 2-множитель.
Ответ 7
Предположим, что у вас есть символы x в буфере обмена и символы x в текстовой области; позвольте называть его "state x".
Позвольте несколько раз нажать "Вставить" (для удобства я обозначаю его m-1
), затем "Выбрать все" и "Копировать"; после этой последовательности мы получаем "состояние m * x".
Здесь мы потратили в общей сложности m + 1 нажатий клавиш.
Таким образом, асимптотический рост есть (по крайней мере) нечто вроде f^n
, где f = m^(1/(m+1))
.
Я считаю, что это максимально возможный асимптотический рост, хотя я не могу его доказать (пока).
Попытка различных значений m показывает, что максимум для f получается для m=4
.
Можно использовать следующий алгоритм:
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
(не уверен, что он оптимальный).
Количество нажатий A в начале - 3: если вы нажмете 4 раза, вы упустите возможность удвоить число A еще на 3 нажатия клавиш.
Количество нажатий на кнопку Вставить в конце не более 5: если у вас осталось 6 или более нажатий клавиш, вы можете вместо этого использовать Вставить, Вставить, Вставить, Выбрать все, Копировать, Вставить.
Итак, мы получаем следующий алгоритм:
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
(не уверен, что он оптимальный). Число символов после выполнения этого похоже на
3 * pow(4, floor((n - 6) / 5)) * (2 + (n - 1) % 5)
.
Примеры значений: 1,2,3,4,5,6,9,12,15,18,24,36,48,60,72,96,144,192,240,288,...
Ответ 8
Далее следует второе редактирование OP, которое вставляет не существующий текст.
Обратите внимание на несколько вещей:
- ^ A и ^ C можно рассматривать как одно действие, которое принимает два нажатия клавиш, так как никогда не имеет смысла делать их индивидуально. Фактически, мы можем заменить все экземпляры ^ A ^ C на ^ K ^ V, где ^ K - однократная "разрезанная" операция (пусть сокращает ее X). Мы увидим, что дело с ^ К намного лучше, чем двузначная ^ А ^ С.
- Предположим, что в буфере обмена начинается "A". Тогда ^ V (пусть сокращенно Y) строго превосходит А, и мы можем отбросить последнее из всех соображений. (В реальной проблеме, если буфер обмена пуст, в дальнейшем мы просто заменим Y на A вместо ^ V вверх до первого X.)
Каждая разумная последовательность нажатия клавиш может быть интерпретирована как группа Ys, разделенная Xs, например YYYXYXYYXY. Обозначим через V (s) число "A, созданное последовательностью s. Тогда V (nXm) = V (n) * V (m), так как X существенно заменяет каждое Y в m на V (n) 'A.
Таким образом, проблема копирования-вставки изоморфна следующей задаче: "используя m + 1 чисел, которые суммируются с N-m, максимизируйте их произведение". Например, при N = 6 ответ равен m = 1 и числам (2,3). 6 = 2 * 3 = V (YYXYYY) = V (AA ^ A ^ C ^ V ^ V) (или V (YYYXYY) = V (AAA ^ A ^ C ^ V).)
Мы можем сделать несколько замечаний:
При фиксированном значении m
номера, которые нужно выбрать, - это ceil( (N-m)/(m+1) )
и floor( (N-m)/(m+1) )
(в любой комбинации выработка суммы, более конкретно вам понадобится (N-m) % (m+1)
ceils
, а остальные floor
> s). Это происходит потому, что для a < b
, (a+1)*(b-1) >= a*b
.
К сожалению, я не вижу простого способа найти значение m
. Если бы это было мое интервью, я бы предложил два решения на данный момент:
Вариант 1. Переверните все возможные m
. Решение O (n log n
).
Код С++:
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;
}
Вариант 2. Разрешить m
достичь нецелых значений и найти его оптимальное значение, взяв производную от [(N-m)/(m+1)]^m
по отношению к m
и решая ее корень. Аналитического решения нет, но корень можно найти, используя, например, Ньютона. Затем используйте пол и потолок этого корня для значения m
и выберите то, что лучше.
Ответ 9
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];
}
Ответ 10
Вот мой подход и решение с кодом ниже.
Подход:
Можно выполнить три различных операции.
- Нажатие клавиши A - выводит один символ 'A'
- Нажатие клавиши (Ctrl-A) + (Ctrl-C) - ничего не выводит. Эти два нажатия клавиш могут быть объединены в одну операцию, потому что каждое из этих нажатий клавиш не имеет никакого смысла. Кроме того, это нажатие клавиши устанавливает выход для следующей операции вставки.
- Нажатие клавиши (Ctrl-V) - вывод для этого нажатия клавиши действительно зависит от предыдущей (второй) операции, и, следовательно, нам нужно будет учитывать это в нашем коде.
Теперь, учитывая три разных операции и их соответствующие выходы, нам нужно выполнить все перестановки этих операций.
Предположение:
Теперь, в некоторой версии этой проблемы указано, что последовательность нажатий клавиш, Ctrl + A → Ctrl + C → Ctrl + V, перезаписывает выделенный выделен. Чтобы повлиять на это предположение, только одна строка кода должна быть добавлена к решению ниже, где печатная переменная в случае 2 установлена на 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;
}
Для этого решения
В приведенном ниже коде будет напечатано несколько последовательностей, и последняя последовательность будет правильным ответом для любого данного N. например. для N = 11 это будет правильная последовательность
С предположением
A, A, A, A, A, C, S, V, V, V, V,: 20:
Без предположения
A, A, A, C, S, V, V, C, S, V, V,: 27:
Я решил сохранить предположение для этого решения.
Обозначение клавиш:
'A' - A
'C' - Ctrl + A
'S' - Ctrl + C
'V' - Ctrl + V
Код:
#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;
}
Ответ 11
Используя трюки, упомянутые в ответах выше, математически Решение можно объяснить в одном уравнении, поскольку
4 + 4 ^ [(N-4)/5] + ((N-4)% 5) * 4 ^ [(N-4)/5].
где [] - наибольший целочисленный множитель
Ответ 12
Существует обмен между печатью m-A вручную, затем с использованием Ctrl + A, Ctrl + C и N-m-2 Ctrl + V. Лучшее решение находится посередине. Если максимальное нажатие клавиш = 10, лучшим решением является ввод 5 A или 4 A.
попробуйте использовать это. Посмотрите на http://www.geeksforgeeks.org/how-to-print-maximum-number-of-a-using-given-four-keys/ и, возможно, немного оптимизируйте результаты вокруг средней точки.
Ответ 13
Вот мое решение с динамическим программированием без вложенного цикла, которое также печатает фактические символы, которые вам нужно ввести:
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]))
Это вывод ('a' означает 'CTRL + A' и т.д.)
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
Ответ 14
Если разрешены клавиши N, то результатом будет N-3.
A → N-3
CTRL + A → Выбор тех N символов: +1
CTRL + C → Копирование тех N символов: +1
CTRL + V → Вставка символов N.: +1
т.е. (поскольку мы выбрали целые символы, используя CTRL + A). Заменяя эти существующие символы N-3 на скопированные символы N-3 (который переопределяет одни и те же символы), а результат - N-3.