检查一个数是不是可以表示为 x 的 2 次方之和?
Posted
技术标签:
【中文标题】检查一个数是不是可以表示为 x 的 2 次方之和?【英文标题】:check wheather a number can be expressed as sum of x powers of two?检查一个数是否可以表示为 x 的 2 次方之和? 【发布时间】:2021-09-14 14:26:50 【问题描述】:是否有任何小技巧可以检查一个数字是否可以表示为 2 的 x 次方之和? 例如:x=3 n=21 数字是 16,4,1 如果 n=30 它应该是假的,因为没有 3 的 2 的幂来表示 30
【问题讨论】:
如果 2 的所有次方都必须不同,则 n 是 2 的 x 次方之和,当且仅当 n 的二进制展开中有 x 个设置位。 如果它们不必不同怎么办? 您的问题似乎是关于数学而不是编程;您可能会在数学网站而不是编程网站上得到更好的答案。我认为我的评论可以更进一步:如果二进制扩展或 n 中有超过 x 个设置位,则 n 不能表示为 x 次方或 2 的总和,即使它们被允许相同。另一方面,如果例如 n = 9 = 2^3 + 2^0(两个设置位),我们可以根据需要将其写为 2^2 + 2^2 + 2^0。祝你好运。 谢谢,在一些实验之后真的有帮助未设置,因为您始终可以根据需要添加 2^0 【参考方案1】:对于一个数字 n……
… 最小 x 是 n 中1
位的数量。这个数字称为 popcount(n)。
示例:二进制数 0b1011
至少需要 popcount(0b1011
)=2 的 3 次方相加 (0b1000
+0b0010
+0b0001
)。
… 最大 x 为 n。因为1
是 2 的幂,所以您可以将 1
添加 n 次得到 n。
现在是一个难题。如果 x 在 popcount(n) 和 n 之间怎么办? 事实证明,所有这些 x 都是可能的。构建两个的 x 次方的总和……
从最短的和(n 的二进制表示)开始 如果您的加数少于 x,则将任何大于 1 的加数拆分为两个加数,将加数的数量加一。这可以在您到达 x=n 之前完成。示例:11=0b1011
可以表示为 x=7 的 2 次方之和吗?
是的,因为 popcount(n)=3
我们使用 x=7 的 2 次方求和
11 = 0b1011
= 0b1000
+0b10
+0b1
|只有3个加数,所以拆分一个
= (0b100
+0b100
)+0b10
+0b1
|只有 4 个加数,所以再拆分一个
= ((0b10
+0b10
)+0b100
)+0b10
+0b1
|只有 5 个加数,所以再拆分一个
= (((0b1
+0b1
)+0b10
)+0b100
)+0b10
+0b1
|只有 6 个加数,所以再拆分一个
= (((0b1
+0b1
)+(0b1
+0b1
))+0b100
)+0b10
+0b1
| 7个加法,完成
实施
为了实现检查»可以将 n 表示为 x 的 2 次方之和吗?« 使用
isSumOfXPowersOfTwo(n, x)
return x<=n && x>=popcount(n).
有关popcount
的有效位旋转实现,请参阅this question。一些处理器甚至有一个指令。
【讨论】:
以上是关于检查一个数是不是可以表示为 x 的 2 次方之和?的主要内容,如果未能解决你的问题,请参考以下文章