【问题标题】:Sum of large exponents of 22的大指数之和
【发布时间】:2016-08-15 01:45:22
【问题描述】:

我正在尝试完成来自hackerrank.com 的编码挑战

Shashank 是一个数学新手,知道给定的基数 N 的 l 有 (2N - 1) 个非空子列表后,他非常兴奋。他记下给定集合 A 的所有非空子列表。对于每个子列表,他计算 sublist_sum,它是元素的总和,并用 S1、S2 表示它们sub>, S3, ... , S(2N-1).

然后他定义了一个 special_sum,P。

P = 2S1 + 2S2 + 2S3 .... + 2S(2N-1) 并报告 P % (10^9 + 7)。

OUPUT 打印 special_sum,P 模 (10^9 + 7)。

我几乎可以肯定我误解了提示,但我的程序旨在接收数字列表。程序会将此列表的所有组合(不重复,顺序无关紧要,所有大小)的 2 提高到幂,然后将它们加在一起并打印出来。

网站上的例子是

列表 1, 1, 2 输出 44

说明

  1. {1} 和 2^1 = 2
  2. {1} 和 2^1 = 2
  3. {2} 和 2^2 = 4
  4. {1,1} 和 2^2 = 4
  5. {1,2} 和 2^3 = 8
  6. {1,2} 和 2^3 = 8
  7. {1,1,2} 和 2^4 = 16

所以总数将是 44;

我对仅将指数相加的理解是错误的,因为答案远大于第一个测试用例中的预期答案(显然)。

输入 422 412 417 497 284 输出 67920854

基本上,我希望有人解释提示。我想我只是在计算部分总和,但我不知道什么时候或我想mod 10^9 + 7

仅供参考,我只完成了代数 II,所以如果我错过了一个数学概念,请在向我解释时记住我的经验。我一直在用 C++ 编程,所以首选该语言的代码示例。

代码我可怜的解决方案:http://pastebin.com/c7YxCLMt

【问题讨论】:

  • "解释提示。"什么?我可以向你保证,2 的 422 次方将比 67920854 大得多。这个问题的第一部分相当清晰;但是在它中途掉下悬崖......完全省略minimal reproducible example也没有帮助。
  • 对不起。我真的不知道该转向哪里。我的问题是概念性的,所以我的源代码没用。我将添加完整的提示
  • 不幸的是,stackoverflow.com 不用于讨论概念问题。但是,更确切地说,是针对特定的技术问题和答案。
  • 部分挑战在于弄清楚如何理解问题。 2^422 是一个非常大的数字。您无法使用简单的操作来计算它。因此,挑战在于看看您是否可以弄清楚如何“重构数学”,以便您可以提供一个简单的计算解决方案。 如果其他人为您解决问题,这将不是您的挑战。 ;)
  • sum 的模是模的和。 (4 + 4) mod 3 = 2 = 4 mod 3 + 4 mod 3。所以你只知道如何从 2^N mod XXX 计算模数,然后求和,这是一个简单的问题

标签: c++ algorithm algebra


【解决方案1】:

没有看到您的尝试,很难说可能是什么缺陷,但有两件事可能是陷阱:

  1. 你提到你应该mod 10^9 + 7,但确保你在做mod (10^9 + 7)
  2. 您正在计算的数字(2^497、2^284 等)巨大而且肯定会溢出。如果你还没有处理这个问题,你可以通过尝试他们正在做的事情来改进你的尝试here

编辑:查看您的代码后,您确实遇到了溢出问题。将here 的想法融入您的解决方案将使您受益。

【讨论】:

    【解决方案2】:

    问题本质上是:给定一个数字列表,找到一个或多个元素的所有可能乘积的总和,其中列表不是给定的列表,而是这些幂的两个。例如,您的示例是 {2, 2, 4} 中的一项或多项的乘积之和。

    我们可以通过查看 0 个或多个元素的乘积之和来进一步简化此过程,然后为我们不想要的空乘积减去 1。这使您可以使用一个巧妙的技巧:对于列表中的每个元素,您将乘以 1 或乘以数字。因此,对于列表 {2, 2, 4},总和为 (2+1)(2+1)(4+1) = 3*3*5 = 45,答案为 45 - 1 = 44。


    这是 PARI/GP 中的一些工作代码。

    specialSum(v, m=10^9+7)=lift(factorback(apply(n -> Mod(2,m)^n+1, v))-1)
    

    用法:

    specialSum([1,1,2])
    specialSum([422,412,417,497,284])
    

    【讨论】:

    • 这对问题中的另一组数字有效吗? 422 412 417 497 284?
    • @smac89 是的。请记住,按照我第一段中的描述,首先将这些数字提高到 2 的幂。
    • @MyLoneTrojan 尽可能简单:对于每个数字 n 计算 2 的 n 次方加一。将所有这些数字相乘并减去 1。
    • @MyLoneTrojan 但您可能首先需要知道如何计算模加法、乘法和求幂。如果没有,您将有大量的数据需要处理,这可能需要更多的努力。
    • @MyLoneTrojan 添加 1 包括或不包括每个因素。如果您展开 (2+1)(2+1)(4+1) 您将得到 8 个产品,并且您试图获得除最小的产品之外的所有产品的总和,即 1。减去 1 即可那个。请参阅我的第二段。
    【解决方案3】:

    基于上面的cmets,我想你对这些算法在线评委不是很熟悉。它们与现实生活中的应用程序不同,它们通常具有极端约束,迫使您使用一些巧妙的技巧及时处理它。 (通常约 1 秒)


    对于这个问题,问题可以分为两部分:

    1. N <= 10^5 时,如何及时求和N^2 整数? (1 秒内)
    2. 如何及时计算2^x % M where x <= 10^5*10^10 = 10^15? (1 秒内)

    当然,在这个过程中,你不能让任何变量溢出,这就是为什么问题要求你输出答案 MOD 10^9 + 7 (我假设你知道模运算的基本性质.)

    对于第 1 点,答案是,你不能。我想暗示的是,有一些方法可以在不求和 N^2 的情况下计算答案项目。我可以根据我接受的解决方案给你一个提示:动态编程,让 DP(N) = 数组 [0..N] 中的项目所需的总和。如果你能制定出DP递归式,你只需将N个整数相加就可以得到答案,可以及时计算出来。

    对于第 2 点,您不能进行任何简单的线性预计算(使用 for 循环和上一次迭代的两倍等)。通过使用上面提到的DP,你只需要计算2^x % M where x <= 10^10,如果你这样做,内存和运行时间约束仍然会失败。这里你需要另一个叫做Exponentiation by squaring 的技巧,它可以在O(lg n) 中计算2^n,因此可以接受。


    结合第 1 点和第 2 点,您可以通过 动态规划平方求幂(以及介于两者之间的一些基本模运算)来解决这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-01
      • 2016-04-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多