【hdu 4658】Integer Partition (无序分拆数、五边形数定理)

本文解析了HDU4658 IntegerPartition题目,探讨了n分拆成若干个正整数之和的问题,每个正整数出现次数小于k。通过五边形数定理和生成函数的方法,提供了O(n^1.5)的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

hdu 4658 Integer Partition

题意

n分拆成若干个正整数的和,每个正整数出现小于k次,分拆方案有多少。(t<=100,n<=1e5)

题解

之前写过一篇Partition Numbers的计算,后面补充了hdu 4651的做法。就是利用五边形数定理。
这题加强了限制条件。

n的无序分拆数的生成函数:
\(\sum_{i=1}^{\infty}B(i)x^i=(1+x+x^2+..)(1+x^2+x^4+..)…=\frac {1}{\prod_{i=1}^{\infty}(1-x^i)}\)

由五边形数定理知

\(\prod_{n=1}^{\infty}(1-x^n)=\sum_{k=0}^\infty (-1)^k x^{\frac {k(3k\pm 1)}{2}}\)

\((1+B(1)x+B(2)x^2+..)(1-x-x^2+x^5+x^7+..)=1\)

比较两边\(x^n\)系数,得到

\(B(n)-B(n-1)-B(n-2)+B(n-5)+B(n-7)+..=0\)

所以可以\(O(n^{1.5})\)计算出B。

有了限制,生成函数变成
\(g(x)=(1+x+x^2+..+x^{k-1})(1+x^2+x^4+..+x^{2(k-1)})…= {\prod_{i=1}^\infty(1-x^{ik})}B(x)\)

再利用五边形数定理得

\(g(x)=(1-x^k-x^{2k}+x^{5k}+..)(1+B(1)x+B(2)x^2+B(3)x^3+..)\)

\(x^n\)的系数即为答案。

代码

int n,k;
int B[N]={1,1,2};
int main() {
    int t;
    sf(t);
    for(int i=3;i<N;++i)
    for(int j=1,f=1;f;++j)
    for(int k=-1;k<2;k+=2){
        int w=(3*j*j+k*j)/2;
        if(w>i){f=0;break;}
        if(j%2)B[i]=(B[i]+B[i-w])%mod;
        else B[i]=(B[i]-B[i-w]+mod)%mod;
    }
    while(t--){
        sf(n);sf(k);
        int ans=0;
        ans=B[n]%mod;
        for(int i=1,f=1;f;++i)
        for(int j=-1;j<2&&f;j+=2){
            int w=(3*i*i+j*i)/2;
            if(w*k>n){f=0;break;}
            if(i%2==0)ans=(ans+B[n-w*k])%mod;
            else ans=(ans-B[n-w*k]+mod)%mod;
        }
        printf("%d\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值