C++动态规划和位运算实现整数分拆数

#include <iostream>
#include <vector>
using namespace std;
void genPart(size_t N) {
    vector<size_t> Penta;
    Penta.emplace_back(1);
    vector<size_t> Part;
    Part.assign(N + 1, 0);
    Part[0] = 1;
    for (size_t i = 1, j = 1; i <= N; i++) {
        size_t nextPenta = Penta[j - 1] + ((j + 1) >> (j & 1));
        if (nextPenta == i) {
            Penta.emplace_back(nextPenta);
            j++;
        }
        for (size_t k = 0; k < Penta.size(); k++) {
            if (k & 2) {
                Part[i] -= Part[i - Penta[k]];
            }
            else {
                Part[i] += Part[i - Penta[k]];
            }
        }
        cout << "Part " << i << " is: " << Part[i] << '\n';
    }
}

int main() {
    size_t n;//n <= 416
    cout << "Enter the number: ";
    cin >> n;
    genPart(n);
    return 0;
}
这个代码利用了五边形数的规律,即数列1,2,5,7,12,15,22,26……
我们可以推导出这个数列的递推公式:A[1]=1,A[2n]=A[2n-1]+n,A[2n+1]=A[2n-1]+2n+1。
从而根据下角标奇偶性的不同,我们可以得出A[n]=A[n-1]+(n >> ((n - 1) & 1))
即当n为偶数时,A[n]等于前一个数加上n/2,当n为奇数时,A[n]等于前一个数加上n


但是为了让代码看起来更统一,我们将下角标往前移一个,令Part[0]=1,便有了
nextPenta = Penta[j - 1] + ((j + 1) >> (j & 1))


在计算整数分割数的部分,我们利用了五边形数与整数分拆数的递推关系

p(k)=p(k−1)+p(k−2)-p(k−5)-p(k−7)+...
至于这个关系的证明过程,可以网上搜索,这里就不过多赘述。
符号的变换关系是++--,正好可以和利用k&2来判断

整体的时间复杂度是O(n^(3/2)),空间复杂度是O(n)

如果你们有更好的算法,还请多多指教,也许算单个整数分拆数的还有更好的算法,但是打表的写法我目前为止,也就只能写到这了。

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值