分拆数
分拆:将自然数
和式中每个正整数称为一个部分。
分拆数:
自
n | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|---|
1 | 1 | 2 | 3 | 5 | 7 | 11 | 15 | 22 |
k 部分拆数¶
将
显然,
如果这个方程里面恰有
相邻两个和式作差,得:
如果列出表格,每个格里的数,等于左上方的数,加上该格向上方数,所在列数个格子中的数。
k | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|---|
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | |
0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | |
0 | 1 | 2 | 1 | 1 | 0 | 0 | 0 | 0 | |
0 | 1 | 2 | 2 | 1 | 1 | 0 | 0 | 0 | |
0 | 1 | 3 | 3 | 2 | 1 | 1 | 0 | 0 | |
0 | 1 | 3 | 4 | 3 | 2 | 1 | 1 | 0 | |
0 | 1 | 4 | 5 | 5 | 3 | 2 | 1 | 1 |
例题¶
计算k部分拆数
计算
观察表格与递推式,按列更新对于存储更有利。不难写出程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #include <stdio.h>
#include <string.h>
int p[10005][1005]; /*将自然数n分拆为k个部分的方法数*/
int main() {
int n, k;
while (~scanf("%d%d", &n, &k)) {
memset(p, 0, sizeof(p));
p[0][0] = 1;
int i;
for (i = 1; i <= n; ++i) {
int j;
for (j = 1; j <= k; ++j) {
if (i - j >= 0) /*p[i-j][j]所有部分大于1*/
{
p[i][j] = (p[i - j][j] + p[i - 1][j - 1]) %
1000007; /*p[i-1][j-1]至少有一个部分为1。*/
}
}
}
printf("%d\n", p[n][k]);
}
}
|
生成函数¶
生成函数:一种幂级数。各项的系数为数列中的对应项。
由等比数列求和公式,有:
对于
Ferrers 图¶
Ferrers 图:将分拆的每个部分用点组成的行表示。每行点的个数为这个部分的大小。
根据分拆的定义,Ferrers 图中不同的行按照递减的次序排放。最长行在最上面。
例如:分拆
将一个 Ferrers 图沿着对角线翻转,得到的新 Ferrers 图称为原图的共轭,新分拆称为原分拆的共轭。显然,共轭是对称的关系。
例如上述分拆
最大
根据共轭的定义,有显然结论:
最大
互异分拆数¶
互异分拆数:
n | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|---|
1 | 1 | 1 | 2 | 2 | 3 | 4 | 5 | 6 |
同样地,定义互异
完全同上,也是这个方程的解数:
这里与上面不同的是,由于互异,新方程中至多只有一个部分非零。有不变的结论:恰有
同样像组合数一样列出表格,每个格里的数,等于该格前一列上数,所在列数个格子中的数,加上该格向上方数,所在列数个格子中的数。
k | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|---|
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | |
0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | |
0 | 1 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | |
0 | 1 | 2 | 1 | 0 | 0 | 0 | 0 | 0 | |
0 | 1 | 3 | 1 | 0 | 0 | 0 | 0 | 0 | |
0 | 1 | 3 | 2 | 0 | 0 | 0 | 0 | 0 |
例题¶
计算互异分拆数
计算互异分拆数
观察表格与递推式,按列更新对于存储更有利。代码中将后一位缩减了空间,仅保留相邻两项。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #include <stdio.h>
#include <string.h>
int pd[50005][2]; /*将自然数n分拆为k个部分的互异方法数*/
int main() {
int n;
while (~scanf("%d", &n)) {
memset(pd, 0, sizeof(pd));
pd[0][0] = 1;
int ans = 0;
int j;
for (j = 1; j < 350; ++j) {
int i;
for (i = 0; i < 350; ++i) {
pd[i][j & 1] = 0; /*pd[i][j]只与pd[][j]和pd[][j-1]有关*/
}
for (i = 0; i <= n; ++i) {
if (i - j >= 0) /*pd[i-j][j]所有部分大于1*/
{
pd[i][j & 1] = (pd[i - j][j & 1] + pd[i - j][(j - 1) & 1]) %
1000007; /*pd[i-j][j-1]至少有一个部分为1。*/
}
}
ans = (ans + pd[n][j & 1]) % 1000007;
}
printf("%d\n", ans);
}
}
|
奇分拆数¶
奇分拆数:
有一个显然的等式:
最左边是互异分拆数的生成函数,最右边是奇分拆数的生成函数。两者对应系数相同,因此,奇分拆数和互异分拆数相同:
但显然
再引入两个概念:
互异偶分拆数:
互异奇分拆数:
因此有:
同样也有相应的
五边形数定理¶
单独观察分拆数的生成函数的分母部分:
将这部分展开,可以想到互异分拆,与互异分拆拆出的部分数奇偶性有关。
具体地,互异偶部分拆在展开式中被正向计数,互异奇部分拆在展开式中被负向计数。因此展开式中各项系数为两方法数之差。即:
接下来说明,多数情况下,上述两方法数相等,在展开式中系数为
这里可以借助构造对应的办法。
画出每个互异分拆的 Ferrers 图。最后一行称为这个图的底,底上点的个数记为
要想在互异偶部分拆与互异奇部分拆之间构造对应,就要定义变换,在保证互异条件不变的前提下,使得行数改变
变换 A:当
变换 B:当
这两个变换,对于多数时候的
变换 A 不能进行的条件:底与坡有一个公共点,且
这时,展开式中第
变换 B 不能进行的条件:底与坡有一个公共点,且
这时,展开式中第
至此,我们就证明了:
将这个式子整理,对比两边各项系数,就得到递推式。
这个递推式有无限项,但是如果规定负数的分拆数是
例题¶
计算分拆数
计算分拆数
采用五边形数定理的方法。有代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #include <stdio.h>
long long a[100010];
long long p[50005];
int main() {
p[0] = 1;
p[1] = 1;
p[2] = 2;
int i;
for (i = 1; i < 50005;
i++) /*递推式系数1,2,5,7,12,15,22,26...i*(3*i-1)/2,i*(3*i+1)/2*/
{
a[2 * i] = i * (i * 3 - 1) / 2; /*五边形数为1,5,12,22...i*(3*i-1)/2*/
a[2 * i + 1] = i * (i * 3 + 1) / 2;
}
for (
i = 3; i < 50005;
i++) /*p[n]=p[n-1]+p[n-2]-p[n-5]-p[n-7]+p[12]+p[15]-...+p[n-i*[3i-1]/2]+p[n-i*[3i+1]/2]*/
{
p[i] = 0;
int j;
for (j = 2; a[j] <= i; j++) /*有可能为负数,式中加1000007*/
{
if (j & 2) {
p[i] = (p[i] + p[i - a[j]] + 1000007) % 1000007;
} else {
p[i] = (p[i] - p[i - a[j]] + 1000007) % 1000007;
}
}
}
int n;
while (~scanf("%d", &n)) {
printf("%lld\n", p[n]);
}
}
|
build本页面最近更新:,更新历史
edit发现错误?想一起完善? 在 GitHub 上编辑此页!
people本页面贡献者:OI-wiki
copyright本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用