我今天遇到了这个问题,在这里我们按升序给出了一个排序数组a[]
,然后我们找到了数字2a1, 2a2, 2a3, ..., 2an
的总和,我们需要找到最小的附加数量类型为2l
(l
的非负数)的整数必须是必需的,以使得所有整数的总和等于2k - 1
对于某个整数k
({{ 1}}是非负的。)
例如:
输入由第一行中的整数n组成。第二个输入行包含n个以空格分隔的整数a(1),a(2),...,a(n)。
示例1:
3
0 1 2
这个案例的答案是0,因为2 0 +2 1 +2 2 = 7已经是2 < sup> k -1,k = 3。
例2:
3
2 4 5
这个案例的答案是3,因为2 2 +2 4 +2 5 = 52并使其成为2 k -1我们有63个所以需要2 0 ,2 1 ,2 3 作为三个术语。
我找到了这个问题来找到总和,然后计算二进制表示中的1的数量,然后回答等于k
。
但我得到的问题是问题中的给定约束
1≤n≤10^ 5
0≤a[i]≤2* 10 ^ 9
有人可以帮忙吗? 我在编程竞赛和2.6 MB内存中接受的解决方案中遇到了这个问题。 因此,存储或获取2 * 10 ^ 9位的数组位并不会更好。我认为会有不同的方法或想法。
答案 0 :(得分:3)
您不需要2 * 10 ^ 9位内存来解决此问题。 n(n <10 ^ 5)上的边界表明了另一种解决方案:
(1)对a_i
:
3 3 3 3 3 5 7 9
(2)通过二进制搜索找到连续副本,摆脱重复。在这种情况下,您有5
(二进制为=101
),因此3 3 3 3 3
变为3 5
。您的a_i
现在是3 5 5 7 9
。 (请注意,这相当于以二进制形式添加数字,但它更高效,因为您知道您的数字最多有10 ^ 9位,但最多设置为10 ^ 5位!)
(3)重复步骤2,直到不再有重复项。在此示例中,您只需要另一个步骤,最后得到3 6 7 9
。
(4)计算max(a_i) - number of a_i left + 1
。这是您的结果,在本例中为9-4+1=6
。
步骤(2)的可能实施:
我要尝试的第一件事就是从头开始覆盖,但保留一个指针来检查我现在的位置,所以:你读了3
。您二进制搜索最后3
并保留指向以下元素的指针。然后,您覆盖:3 3 3 3 3 5 7 9
- &gt; 3 5 x x x *5 7 9
(x
位置的内容并不重要,指针现在位于5
。现在,对于第一个解决方案,只需从末尾复制所有内容,使其再次连续:3 5 5 7 9
并记住您的数组现在更短。
这是不是最有效的解决方案,因为如果你有像3 3 4 4 5 5 6 6...
这样的数组会导致很多复制,但它应该足够好。
为了获得更好的性能,您只能执行步骤(1),然后将所有内容插入到将a_i
映射到其显示次数的哈希映射中,然后对该哈希映射进行操作。这对于你的约束非常快,但在C中实现一个hashmap并不是一件容易的事。
答案 1 :(得分:0)
您需要做的是使用位数组。
您需要 i &lt; = 2 * 10 9 (20亿)。要表示20亿位,您需要大约256MB的内存(每个字节存储8位)。您可能需要创建一些方便的抽象层,它将提供.get(int n)
,.set(int n)
等函数,这些函数将读取并保存该位数组中的位。
要分配数组,请使用malloc
:
typedef byte unsigned char;
// 256MB, enough for 2 billion bits
byte * bit_array = malloc(256*1024*1024);
// or use calloc, which initializes to 0:
byte * bit_array = calloc(256*1024*1024, 1);
要设置位n,请使用以下分配:
bit_array[n/8] |= 1 << (n % 8);
要获得位n,请使用以下表达式:
(bit_array[n/8] >> (n % 8)) & 1
你的算法可能是这样的: