关于数论的算法

时间:2013-12-14 13:57:10

标签: c++ algorithm

给出两个正整数a,b(1 <= a&lt; = 30,1&lt; = b&lt; = 10000000),并定义两个不可重复的集合L和R,

L = {x * y | 1 <= x <= a, 1 <= y <= b, x,y is integer}

R = {x ^ y | 1 <= x <= a, 1 <= y <= b, x,y is integer},

^是XOR操作

对于任何两个整数:A∈L,B∈R,我们将B格式化为n + 1(n是b的十进制数字)十进制数字(在B前填充0),然后将B关联到结束A并得到一个新的整数AB。

计算所有生成的整数AB的总和(如果总和超过,只返回“sum mod 1000000007”,mod表示模块化操作)

注意:算法的时间不超过3秒

我的算法非常简单:我们可以很容易地得到集合R中的最大数字,而R中的元素是0,1,2,3 ... maxXor,(元素max( a,b)可能不在R)中,使用哈希表计算集合L. 但是当a = 30,b = 100000 时算法消耗4秒。


举个例子:

a = 2, b = 4, so

L = {1 * 1, 1 * 2, 1 * 3, 1 * 4, 2 * 1, 2 * 2, 2 * 3, 2 * 4} =  {1, 2, 3, 4, 6, 8}

R =  {1^1,1^2,1^3,1^4,2^1,2^2,2^3,2^4} =  {0, 1, 2, 3, 5, 6}

所有生成的整数AB是:

{

100, 101, 102, 103, 105, 106,

200, 201, 202, 203, 205, 206,

300, 301, 302, 303, 305, 306,

400, 401, 402, 403, 405, 406,

600, 601, 602, 603, 605, 606,

800, 801, 802, 803, 805, 806

}

所有 AB 总和14502

1 个答案:

答案 0 :(得分:8)

因此AB号可以写成10^(n+1) A + B。这意味着对所有A, B求和,总数等于

|R| 10^(n+1) Sum(A in L) + |L| Sum(B in R)

在您的示例中,

|L| = 6
|R| = 6
Sum(A in L) = 24
Sum(B in R) = 17
n = 3

当插入上述公式时给出14,502。

这会将集合大小的运行时间从二次变为线性,因此您应该会看到相当大的改进。

接下来的一点我没有完全充实,因为我没有时间,但他们觉得他们应该工作:

  • 首先,请注意Sum(A in L)使用

    进行计算是微不足道的
    1 + 2 + .. + n = n(n-1)/2
    

    如果没有L不包含重复的约束。你可以通过利用a非常小的事实来解决这个问题:使用三角数公式迭代计算总和1, .., a并使用该信息来避免多次计算产品。

  • 对于Sum(B in R),请注意,当您比较yx^y时,最多lg(a)位已更改。因此,您可以将x^y s的总和分成两个总和:一个处理来自lg(a)+1的位,一个仅取决于b,另一个处理更复杂的总和来自lg(a)的位向下,取决于ab

编辑:OP要求我扩展如何快速计算Sum(A in L)。在以前的编辑中,本节中有一些东西,但实际上我已经坐下来完成了它,而不是随意地将它击打在我脑海中。事实证明它比我想象的要复杂得多,所以我很抱歉没有坐下来尽快完成它@tenos。

因此,我们要做的是将所有不同产品x*y的总和作为1 <= x <= a1 <= y <= b。好吧,事实证明这很难,所以让我们从一个更简单的问题开始:给定两个整数x1, x2x1 < x2,我们如何计算所有不同产品x1*y或{{的总和1}} x2*y

如果我们放弃了清晰度标准,这很容易:它只是

1 <= y <= b

其中x1*Sum(b) + x2*Sum(b) 表示整数Sum(j)1的总和,并且可以使用高斯的三角数公式计算。因此,我们可以将问题简化为更简单的问题:我们如何才能找到左右两个项中出现的所有产品的总和?

如果

,两种产品是平等的
j

这恰好发生在x1*y1 == x2*y2 ,其中x1*y1 == x2*y2 == k*LCM(x1, x2)lowest common multipleLCM是某个整数。

所有k的总和,k

1 <= k*LCM(x1, x2) <= x1*b

其中R(x1, x2) = LCM(x1, x2) * Sum(x1*b/LCM(x1, x2)) 代表“重复”。这意味着我们所有不同产品的总和Rx1*y其中x2*y

1 <= y <= b

接下来,让我们将x1*Sum(b) + x2*Sum(b) - R(x1, x2) 的定义扩展为三个变量R定义为

x1 < x2 < x3

并且类似地对于4个变量,5个变量等。然后,三个R(x1, x2, x3) = LCM(x1, x2, x3) * Sum(x1*b/LCM(x1, x2, x3)) 的不同产品的总和是

x1 < x2 < x3

inclusion-exclusion principle

所以,让我们来利用它。定义

x1*Sum(b) + x2*Sum(b) + x3*Sum(b) - R(x1, x2) - R(x1, x3) - R(x2, x3) + R(x1, x2, x3)

等。然后,所有这些总和的总和最多Sum for x = 1: 1*Sum(b) Sum for x = 2: 2*Sum(b) - R(2, 1) Sum for x = 3: 3*Sum(b) - R(3, 2) - R(3, 1) + R(3, 2, 1) 是所有不同产品的总和。

编辑:@tenos把它变成了一个有用的解决方案。他注意到,由于i * Sum(b)包含许多重复,我们可以用i * sum(k ... b)替换,k = max(b / minPrimeFactor(i)+ 1,i)。

此外,当使用包含 - 排除原理时,可以修剪许多不必要的计算。例如,如果R(1,2)= NULL,则不需要计算R(1,2,3),R(1,2,4)..等等。实际上,当b非常大时,有很多R(i,.. j)= NULL。