专栏文章
next_permutaion 与 Gosper's Hack
个人记录参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mioxlw6p
- 此快照首次捕获于
- 2025/12/03 02:48 3 个月前
- 此快照最后确认于
- 2025/12/03 02:48 3 个月前
next_permutation 的实现
CPPbool nxtp(){
int i=n-1;
for(;i>=1;i--)if(a[i]<a[i+1])break;
if(!i)return 0;
int j=n;
for(;j>=1;j--)if(a[i]<a[j])break;
std::swap(a[i],a[j]);
std::reverse(a+1+i,a+1+n);
return 1;
}
没什么多说的,就是上面这么做的。
next_permutaion 均摊复杂度证明
方法:得到每次最长下降后缀长度之和,除以 就是答案。
- 打表找规律
- 递推
- 数学计算
打表找规律
递推
数学
某些表格看横再看竖,能有不同发现。
从 个数里分别选 个, 个, 个,使得其后面 个数是递减的。
从 个数里分别选 个, 个, 个,使得其后面 个数是递减的。
结论
三种方法可得 。
所有均摊复杂度是
因此均摊时间复杂度为 。
所有均摊复杂度是
因此均摊时间复杂度为 。
Gosper's hack
给你一个二进制数 ,请算出第一个比 大且 的数量与 相同的数。
不难想到,做一遍 next_permutaion 即可。
但 Gosper 想出了仅用算数就做出来的方法 。
不难想到,做一遍 next_permutaion 即可。
但 Gosper 想出了仅用算数就做出来的方法 。
Gosper's hack 解法
引用 Deepseek 的解释。
推导公式
现在,让我们尝试从原理上推导出这个公式。我们需要从一个有k个1的二进制数x,生成下一个有k个1的二进制数。
Gosper's Hack 算法详解
1. 找到最右边的可移动 1
设当前数为 ,其二进制表示为:
其中:
- 下划线标记的是最右边连续 1 块的最左侧 1
- 该位置的值可通过低位运算得到:
2. 移动该 1 位
将该 1 向左移动一位:
效果示例:
3. 处理右侧的 1
移动后需要补回因进位而丢失的 1:
- 计算异或:
- 调整步骤:
先把高位用异或消掉,然后将 放到结尾,最后会多两个 ,直接右移截断。
至于为何会多两个 ,自己想。
至于为何会多两个 ,自己想。
4. 组合结果
最终的下一个数为:
| 步骤 | 数字 |
|---|---|
本课要点
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...