五边形数定理 Pentagon Number Theorem(整数拆分)
更新日志
2025/06/25:开工。前言
虽然名字叫五边形数定理,且确实与五边形数有关,但这个定理的重点事实上完全不在五边形数上。
这个定理可以 \(O(n\sqrt n)\) 解决任意整数的拆分方案问题,详见例题部分。
本文参考了 SF的文章,在此拜谢。
由于证明并非 OI 中的重点,且网上已有一定量的详细证明,所以有一些非必要的证明过程作者会进行一定省略,但一般会在相应位置放上外链。
本文自认为较为详细地讲解了整数拆分问题的生成函数推导过程。
五边形数
友情提示:本部分可以跳过。
其几何意义就不说了,其递推式为:
然后我们可以简单地推出其通项公式:
然后是广义五边形数,不再限定 \(n\) 为正整数。我们可以得到如下数列:
对这个数列有一点印象就行了,等下我们会再遇到它。
欧拉函数与五边形数定理
注意,这里的欧拉函数 \(\phi(x)\) 并非数论中那个欧拉函数 \(\varphi(x)\)。
详细展开过程我就略了,此展开式由欧拉提出,若感兴趣可以自行搜索。
然后整个定理唯一和五边形数有关的部分出现了:注意到欧拉函数展开式中 \(x\) 的次数是广义五边形数。于是这个定理便被称之为五边形数定理。也许是为了与欧拉定理做区分吧。
我们将欧拉函数升幂排序可得:
整数拆分
求将一个正整数拆分为多个可重正整数之和的方案数。
这里推导一下这个问题的生成函数。
令 \(ax^b\) 式系数 \(a\) 表示方案数,\(b\) 表示组成的数。
数 \(i\) 的贡献序列的通项公式为:
这里简单证明一下,首先你应当知道 \(\frac{1}{1-x}=\sum\limits_{k=0}^{\infty}x^k\)。如果你不会这个的话,请自行学习生成函数入门或者跳过这段证明。
然后 \(\frac{1}{1-x^{b}}=\sum\limits_{k=0}^{\infty}x^{kb}\),两边的 \(x\) 同时 \(b\) 次方可得。证毕。
那么我们将所有数的贡献多项式相乘即可得到这个问题的生成函数,此时次数 \(b\) 的项的系数即为方案数,记作 \(p(b)\)。
这时候我们发现:
我们使用五边形数定理展开可得:
接下来我们尝试推出 \(p(x)\) 的递推式,上述等式左右两边各项系数相等,那么除了 \(0\) 次项外系数均为 \(0\)。
那么我们可以得出 \(k\) 次项的系数为:
于是我们有了递推式:
五边形数的量级是 \(\sqrt{n}\) 的,因为其通项为 \(\frac{3n^2-n}{2}\)。所以我们每次暴力枚举递推的复杂度是 \(O(n\sqrt n)\) 的。
整数拆分-各数上限
要求拆分后每个正整数数量小于 \(k\) 的方案数。
我们先推导一下这个问题的生成函数:
定义同上,数 \(i\) 贡献序列的通项为:
这个公式是这么推来的:
作差即可。
因此这个问题的生成函数即为:
注意这里的系数用 \(p'\) 表示,\(p\) 表示无上限问题生成函数系数。
然后我们发现:
于是:
由五边形数定理展开得:
因而我们可以由 \(p\) \(O(\sqrt n)\) 求得 \(p'\):
整体复杂度 \(O(n\sqrt n+q\sqrt n)\)。
例题及模板
code
int n;
mint f[N];
inline int Ptg(int x){return 3*x*x-x>>1;}
inline void Main(){
read(n,mod);
f[0]=1;
rep(i,1,n){
rep(j,1,inf){
int x=Ptg(j),y=Ptg(-j);
if(x<=i)f[i]+=(j&1?1:mod-1)*f[i-x];
if(y<=i)f[i]+=(j&1?1:mod-1)*f[i-y];
else break;
}
}
put(f[n]);
}
code
const int N=1e5+5;
int n,k;
mint f[N];
inline int Ptg(int x){return 3*x*x-x>>1;}
inline void Main(){
read(n,k);
mint ans=f[n];
rep(j,1,inf){
int x=Ptg(j),y=Ptg(-j);
if(x*k<=n)ans+=(j&1?mod-1:1)*f[n-x*k];
if(y*k<=n)ans+=(j&1?mod-1:1)*f[n-y*k];
else break;
}
put(ans);
}
int main(){
f[0]=1;
rep(i,1,1e5){
rep(j,1,inf){
int x=Ptg(j),y=Ptg(-j);
if(x<=i)f[i]+=(j&1?1:mod-1)*f[i-x];
if(y<=i)f[i]+=(j&1?1:mod-1)*f[i-y];
else break;
}
}
// ReadFile(___);
#define MultiTasks
#ifdef MultiTasks
int t;read(t);while(t--)
#endif
Main();
return 0;
}

浙公网安备 33010602011771号