使用按键A,Ctrl + A,Ctrl + C和Ctrl + V的最大字符数


106

这是谷歌的采访问题。我自己无法解决。有人可以照亮吗?

编写一个程序来打印击键序列,以使其生成最大数量的字符“ A”。您只能使用4个键:ACtrl+ ACtrl+ CCtrl+ V。仅允许N次击键。所有Ctrl+字符都被视为一次击键,因此Ctrl+ A是一次击键。

例如,序列ACtrl+ ACtrl+ CCtrl+ V在4次击键中生成两个A。

  • Ctrl + A为全选
  • Ctrl + C为复制
  • Ctrl + V为粘贴

我做了一些数学。对于任何N,使用x个数字的A,一个Ctrl+ A,一个Ctrl+ C和y Ctrl+ V,我们可以生成最大((N-1)/ 2)2个数字的A。对于某些N> M,最好使用尽可能多的Ctrl+ ACtrl+ CCtrl+ V序列,因为它将A的数量加倍。

序列Ctrl+ ACtrl+ VCtrl+ C不会覆盖现有选择。它将复制的选区附加到所选的选区。


在许多文本编辑器^A中,通常是“全选”,^C“复制”,^V“粘贴”。那给你个主意吗?
Nikolai Fetissov 2011年

我的意思是“ A”的数量。例如,对于N = 7,我们可以使用击键A,A,A,CTRL + A,CTRL + C,CTRL + V,CTRL + V
munda

嗯,这是7击键。
John Dibling 2011年

@John“所有CTRL +字符都被视为一个按键,因此CTRL + A是一个按键。”
弗雷德里(Fredley)2011年

1
我删除了C ++标记,这纯粹是一个算法问题,希望它将防止不满意的c ++追随者降低投票率/投票结束。
Matthieu M.

Answers:


43

有一个动态的编程解决方案。我们从知道0键可以使我们获得0 A开始。然后,我们i最多重复进行以下操作n,执行两项操作:按一次A,然后按全选+复制,然后粘贴j时间(实际上j-i-1在下面;请注意此处的技巧:内容仍在剪贴板中,因此我们可以多次粘贴它而无需粘贴每次复制)。我们最多只需要考虑4个连续粘贴,因为选择,复制,粘贴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,因此我们需要添加1make j-i-1。这解释了j-i-1倒数第二行。

以下是一些结果(n=> A的数量):

  • 7 => 9
  • 8 => 12
  • 9 => 16
  • 10 => 20
  • 100 => 1391569403904
  • 1,000 => 3268160001953743683783272702066311903448533894049486008426303248121757146615064636953144900245 174442911064952028008546546304
  • 50,000 => 非常大的数字!

我同意@SB,您应该始终陈述自己的假设:我的意思是,您无需粘贴两次就可以使字符数增加一倍。这将得到7的答案,因此,除非我的解决方案错误,否则假设必须正确。

如果有人想知道为什么我没有检查形式的序列Ctrl+ ACtrl+ CACtrl+ V:最终的结果总是一样的ACtrl+ ACtrl+ CCtrl+ V考虑。


n => result还是result => n?无论哪种方式,我认为都是错误的。我们可以通过7次击键键入9 As。如果是的n => result话,那肯定是错误的。您可以输入的As数量不能少于n
IVlad 2011年

@IVlad是n => result。您说“我可以输入7和7次击键”,这就是我得到的。阅读“绝招”我刚刚编辑英寸
moinudin

这看起来很好,除了问题是要找到给定数量的击键的最大As数,而不是获得给定数量的As的最小击键数。
Andrew Clark

1
@marcog-您的符号至少令人困惑,而且至多是错误的。n是允许您使用的按键。您必须计算多少n击击次数。所以7 => 7没有道理。
IVlad 2011年

1
看起来不错,+ 1。现在让我们看看是否有人可以将其降低到O(n)甚至O(1):)。
IVlad 2011年

41

通过使用marcog的解决方案,我发现了一个以开头的模式n=16。为了说明这一点,这里提供了n=24高达的击键,n=29为了提高可读性,我将^ A替换为S(选择),将^ C替换为C(复制),将^ V替换为P(粘贴),以提高可读性:

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之后,理想的模式是选择,复制,粘贴,粘贴,粘贴和重复。每5次击键会将As的数量乘以4。如果这5个击键模式无法自己消耗其余的击键,则一定数量的4个击键模式(SCPP)消耗了最终的击键,并根据需要更换SCPPP(或除去其中的一种焊膏)。每4次击键,这4种击键模式会将总数乘以3。

这里使用这种模式的是一些Python代码,其结果与marcog的解决方案相同,但是是O(1)编辑:由于取幂,实际上是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,模式总数就会增加1 n / 5。使用地板分割,我们可以获得模式的总数,的总数e4是模式的总数减去e3。对于不熟悉Python的人来说,//是面向未来划分地板的标记。


1
好一个!经过测试,适用于n=3000,所以可能是正确的。(可惜我今天没有投票权:/)
moinudin 2011年

5
+1,非常好。较小的nitpick:并不是O(1)因为不能在恒定时间内进行求幂。是O(log n)
IVlad 2011年

2
实际上,序列“ SCPPP”只会将字符数乘以三:第一个粘贴仅覆盖所选文本。
尼克·约翰逊

4
@Nick问题的最后一行:“序列Ctrl + A,Ctrl + V,Ctrl + C不会覆盖现有选择。它将复制的选择附加到所选的选择上。”
moinudin

2
@marcog是的,我没有注意到。不过,我不知道有任何操作系统会以这种方式运行。
尼克·约翰逊

15

这是我的处理方法:

  • 假设CtrlA=全选
  • 假设CtrlC=复制选择
  • 假设CtrlV=粘贴复制的选择

给定一些文本,需要4次击键才能复制它:

  • CtrlA 全部选择
  • CtrlC 复制它
  • CtrlV 粘贴(这将粘贴在所选内容上-陈述您的假设)
  • CtrlV 再次粘贴,将其加倍。

从那里,您可以考虑做4或5 A,然后遍历上面的内容。请注意,这样做ctrl + a, c, v, v将使您的文字在循环播放时呈指数增长。如果剩余笔划<4,则继续CtrlV

在Google之类的地方进行访谈的关键是陈述您的假设并传达您的想法。他们想知道您如何解决问题。


6
关于面试技巧的要点是,获得正确答案并不比最终清晰地交流重要!
弗雷德里(Fredley)2011年

2
好答案。对于该算法,贪婪关闭逐两个误差:ACVV-VVVVV乘以7,ACVV-ACVV-V6乘以6.所以按Ctrl-V剩余笔划<代替4
马塞尔Jackwerth

5

在O(1)中是可解决的:与斐波那契数一样,有一个公式可以计算打印的As数(以及击键顺序):


1)我们可以简化问题描述:

  • 仅具有[A],[Ca] + [Cc],[Cv]和空的复制粘贴缓冲区

等于

  • 复制粘贴缓冲区中仅包含[Ca] + [Cc],[Cv]和“ A”。

2)我们可以将击键序列描述为{'*','V','v'}中N个字符的字符串,其中'v'表示[Cv],'*'表示[Ca]和'V '表示[抄送]。示例:“ vvvv * Vvvvv * Vvvv”

该字符串的长度仍等于N。

该字符串中Vv字长度的乘积等于所产生的As的数量。


3)给定该字符串的固定长度N和固定数量的单词K,如果所有单词的长度几乎相等,则结果将是最大的。它们的成对差不超过±1。

现在,如果给定N,最优数K是多少?


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)或通过将前一个单词的长度从4调整为3来附加一个长度为3的单词:4 * 4 * 4 * 2 = 128 <4 * 4 * 3 * 3 = 144。

    b)将3个单词增加到5个长度:5 * 5 * 5 = 125。=>附上一个词比较好。

  • 如果还有2:我们可以

    a)或通过将前面的两个单词从长度4调整为3:来附加一个长度为3的单词:4 * 4 * 1 = 16 <3 * 3 * 3 = 27。

    b)将2个单词增加到5个长度:5 * 5 = 25。=>附上一个词比较好。

  • 如果还剩下1:我们可以

    a)或通过将前面的三个单词从长度4调整为3:来附加一个长度为3的单词:4 * 4 * 4 * 0 = 0 <3 * 3 * 3 * 3 = 81。

    b)增加一个单词至5:4 * 4 * 5 = 80。=>附上一个词比较好。


6)现在,如果我们没有“足够大的N”来使用5)中的规则怎么办?如果可能,我们必须遵守计划b)!小N的字符串为:

1:“ v”,2:“ vv”,3:“ vvv”,4:“ vvvv”

5:“ vvvvv”→5 (方案b)

6:“ vvvvvvv”→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)现在,长度为N的字符串中的最佳单词数K是多少?

如果N <7,则K = 1,否则,如果6 <N <11,则K = 2; 否则:K = ceil((N + 1)/ 5)

用C / C ++ / Java编写: int K = (N<7)?(1) : (N<11)?(2) : ((N+5)/5);

如果N> 10,则长度为3的单词数将为:K * 5-1-N。这样,我们可以计算出打印为:

如果N> 10,则As的数目为: 4 ^ {N + 1-4K}·3 ^ {5K-N-1}


似乎是正确的,适用于@Andrew的答案给出的示例,但是您的答案也是O(log N)而不是O(1),对吗?
rsenna 2011年

怎么可能是O(log N)?在O(1)中计算出计算As数的数学公式。因为要打印O(N)个键,所以打印键的算法是O(N),或者如果您允许以正则表达式打印,则算法是O(1)。
2011年

计算乘幂为O(log N),因为4上的指数随N增加。如果以因子形式打印出As的数量,则为O(1)。
安德鲁·克拉克

喔好吧。从未考虑过使用整数算术实际计算数字。我只会对公式或浮点近似感兴趣。但是,当然,为了能够将其与其他数字进行比较,必须进行精确计算。
2011年

5

仅在4'A之后使用CtrlA+ CtrlC+ CtrlV是一个优势。

因此,我将执行以下操作(使用伪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's use them with simple CTRL-Vs
FOR I IN N1 TO N
    PRINT 'CTRL-V'
NEXT

编辑

  1. 返回CtrlV在主循环中使用单个。
  2. 添加了一些评论来解释我在这里想要做什么。
  3. 修复了“前四个A's”块的问题。

@SB:我仅对LAST粘贴执行CTRL-V 。顺便说一句,这正是您在回答中所说的。这意味着我们的想法相似,所以我不知道您为什么批评我-也许我错过了什么?
rsenna 2011年

1
谷歌从来没有指定一种适当的语言来写,无论你想要什么。
惊吓

3

需要3次击键才能使您的As数量加倍。仅当您已打印3个或更多As时才开始加倍。您希望您最后允许的击键次数是a CtrlV,以确保您将最大的击键次数加倍,因此为了对齐它,我们将在开始的三个击键之后填充更多的击键,并在开始时添加更多的击键。

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");
}

编辑:

这太糟糕了,我完全超越了自己,没有为每个副本考虑多个粘贴。

编辑2:

我相信,如果您有足够的击键次数,则最好粘贴3次。在5次击键中,您将As数乘以4。这比使用4次击键将3乘以更好,并且优于使用6次击键将5乘以5。我通过给每种方法相同的击键次数进行比较,以使它们每个都可以同时完成一个循环(60),让3乘数执行15个循环,让4乘数执行12个循环,然后使5乘以5。乘数做10个周期。3 ^ 15 = 14,348,907、4 ^ 12 = 16,777,216和5 ^ 10 = 9,765,625。如果只剩下4次击键,则执行3乘子的操作要比粘贴4次更好,这实际上使先前的4乘子成为8乘子。如果只剩下3次击键,则最好是2倍。


2

假设剪贴板中有x个字符,文本区域中有x个字符;我们称之为“状态x”。

让我们按几次“粘贴”(m-1为方便起见,我用“表示”表示),然后按“全选”和“复制”。在此序列之后,我们进入“状态m * x”。在这里,我们总共浪费了m + 1次按键。因此,渐近增长至少为f^n,其中f =m^(1/(m+1))。我相信这是最大可能的渐近增长,尽管我还不能证明。

尝试m的各种值表明,对于 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次,则错过了再3次击键时A的数量翻倍的机会。

最后按下“粘贴”的次数不超过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,...


2

接下来的操作使用OP的第二次编辑,粘贴不会取代现有的文字。

注意几件事:

  • 可以将^ A和^ C视为一个需要两次击键的动作,因为单独进行两次击键是没有意义的。实际上,我们可以用^ K ^ V替换所有^ A ^ C实例,其中^ K是一键式 “剪切”操作(我们将其缩写为X)。我们将看到处理^ K比花费两个成本的^ A ^ C好得多。
  • 假设剪贴板中有一个“ A”。然后^ V(缩写为Y)严格优于A,我们可以从所有考虑中删除后者。(在实际问题中,如果剪贴板开始为空,接下来我们将Y替换为A而不是^ V直到第一个X。)

因此,每个合理的击键序列都可以解释为一组由Xs分隔的Ys,例如YYYXYXYYXY。用V(s)表示由序列s产生的'A'的数目。那么V(nXm)= V(n)* V(m),因为X本质上用m(n)'A代替m中的每个Y。

因此,复制粘贴问题与以下问题同构:“使用m + 1个数字之和为Nm,使它们的乘积最大化。” 例如,当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的)。这是因为,对于a < b(a+1)*(b-1) >= a*b

不幸的是,我没有找到找到价值的简单方法 m。如果这是我的采访,那么我现在将提出两个解决方案:

选项1.循环所有可能 m。O(n log n)解决方案。

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;
}

选项2允许m通过取导数以获得非整数值,并找到它的最佳值[(N-m)/(m+1)]^m相对于m并求解其根。没有解析解,但是可以使用例如牛顿法找到根。然后使用该根的地板和天花板作为的值m,并选择最佳者。


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

这是我的方法和下面的代码的解决方案。

方法:

可以执行三种不同的操作。

  1. 按键A-输出一个字符“ A”
  2. 击键(Ctrl-A)+(Ctrl-C) -本质上不输出任何内容。这两个击键可以组合为一个操作,因为每个击键都没有意义。同样,此按键设置了下一个粘贴操作的输出。
  3. 击键(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;
}    

0

使用以上答案中提到的技巧,在数学上,解决方案可以用以下等式解释:

4 + 4 ^ [(N-4)/ 5] +((N-4)%5)* 4 ^ [(N-4)/ 5]。其中[]是最大整数因子



0

这是我的动态编程解决方案,没有嵌套循环,并且还打印了您需要键入的实际字符:

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 

0

如果允许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。


欢迎来到StackOverflow!了解如何添加内容格式以及如何使用实际的箭头符号。这将提高您答案的可读性!
M. Mimpen
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.