给出两个正整数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
答案 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)
,请注意,当您比较y
和x^y
时,最多lg(a)
位已更改。因此,您可以将x^y
s的总和分成两个总和:一个处理来自lg(a)+1
的位,一个仅取决于b
,另一个处理更复杂的总和来自lg(a)
的位向下,取决于a
和b
。
编辑:OP要求我扩展如何快速计算Sum(A in L)
。在以前的编辑中,本节中有一些东西,但实际上我已经坐下来完成了它,而不是随意地将它击打在我脑海中。事实证明它比我想象的要复杂得多,所以我很抱歉没有坐下来尽快完成它@tenos。
因此,我们要做的是将所有不同产品x*y
的总和作为1 <= x <= a
和1 <= y <= b
。好吧,事实证明这很难,所以让我们从一个更简单的问题开始:给定两个整数x1, x2
和x1 < 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 multiple且LCM
是某个整数。
所有k
的总和,k
为
1 <= k*LCM(x1, x2) <= x1*b
其中R(x1, x2) = LCM(x1, x2) * Sum(x1*b/LCM(x1, x2))
代表“重复”。这意味着我们所有不同产品的总和R
或x1*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。