math - 检查一个数字是否可以表示为 x 的 2 次方之和?
问题描述
是否有任何技巧可以检查一个数字是否可以表示为 2 的 x 次方之和?例如:x=3 n=21 如果 n=30,数字是 16,4,1 它应该是假的,因为没有 3 的 2 的幂来表示 30
解决方案
对于一个数字 n ...</p>
- ... 最小 x 是
1
n 中的位数。这个数字称为popcount(n)。
示例:二进制数0b1011
至少需要 popcount(0b1011
)=3 的 2 次方相加 (0b1000
+0b0010
+0b0001
)。 - ... 最大 x 是 n。因为
1
是 2 的幂,所以可以加1
n 次得到 n。
现在来了一个难题。如果 x 在 popcount(n) 和 n 之间怎么办?
事实证明,所有这些 x 都是可能的。构建两个的 x 次方的总和……</p>
- 从最短的和开始(n 的二进制表示)
- 如果您的加数少于 x,则将任何大于 1 的加数拆分为两个加数,将加数的数量加一。这可以在您到达 x=n 之前完成。
示例: 11=0b1011
可以表示为 x=7 的 2 次方之和吗?
是的,因为 popcount(n)=3 <= x=7 <= n=11。
要构建 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
请参阅此问题。一些处理器甚至有一个指令。
推荐阅读
- date - 如何使用时刻将字符串日期转换为 unix 格式
- php - 在没有关闭模式的情况下替换后刷新模式窗口中的图像
- r - 在互联网断开的机器上安装存储库时如何绕过 repos 错误?
- python - 蟒蛇 | 在字典中添加 2 个相同的键
- ruby-on-rails - 在rails中拆分字符串并附加单引号
- apache-spark - Hadoop CLI 命令获取使用的总内存等,如 8088 上的 Hadoop Web UI 中所示
- asp.net-core - 从所有会话中注销 IdentityServer4
- node.js - 如何为 express-session 的 req.session.destroy() 编写简单的 Jest 模拟
- php - 我希望能够删除问题/答案(选择)和主题 Codeigniter 从数据库中删除记录
- c# - 当我使用 T4 Templete 创建这个列表时,它给了我一个异常 NullReferenceException