您的位置:首页 > 其它

题目90:整数划分

2017-11-28 23:38 381 查看

题目链接:

http://acm.nyist.net/JudgeOnline/problem.php?pid=90

描述

将正整数n表示成一系列正整数之和:n=n1+n2+…+nk,

其中n1≥n2≥…≥nk≥1,k≥1。

正整数n的这种表示称为正整数n的划分。求正整数n的不

同划分个数。

例如正整数6有如下11种不同的划分:

6;

5+1;

4+2,4+1+1;

3+3,3+2+1,3+1+1+1;

2+2+2,2+2+1+1,2+1+1+1+1;

1+1+1+1+1+1。

输入

第一行是测试数据的数目M(1<=M<=10)。以下每行均包含一个整数n(1<=n<=10)。

输出

输出每组测试数据有多少种分法。

样例输入

1

6

样例输出

11

算法思想:

生成函数解法(组合数学中应用的母函数)。

先简单说明一下生成函数吧,下面是一个生成函数,



xk的系数ak代表了可获得数字k的组合数。

那么回到我们的问题中,我们怎么用生成函数去解决呢?

类似的,我们可以计算生成函数:



我们来做一个说明,第i个括号(1+xi+x2i+x3i · · ·)选择的元素代表了数字i在我们最终的划分中出现的次数,具体而言,如果我们在第i个括号中选择了元素 xc(i) * i 则表示数字 i 在我们最终的划分中出现了c(i)次。如果我们把最终从每个括号里面选择出来的元素相乘 x1 * c(1) · x2 * c(2) · x3 * c(3) · · · = x c(1) + 2 * c(2) + 3 * c(3)···.那么,xn的系数就是我们可以获得多少种不同的方式使得c(1) + 2 * c(2) + 3 * c(3)··· = n,也就是n的划分数(其中,c(i)代表了在一次划分中数字 i 的出现次数)。比如说25=6+4+4+3+2+2+2+1+1,用上式表示就是25=1(2)+2(3)+3(1)+4(2)+5(0)+6(1),也就是在划分中有两个1,三个2,一个3,两个4,0个5以及一个6。

假设x<1,那么我们可以将上面的生成函数表示为:



考虑到我们能选择的最大的数 i 是 m ,所以真正计算的时候我们需要对上面的生成函数式子做一下修改:

G(x) = (1+x+x^2+x^3+…+x^n) (1+x^2+x^4+…) (1+x^3+x^6+…) … (1+x^m)

= g(x,1) g(x,2) g(x,3) … g(x, n)

源代码

/*
Author:杨林峰
Date:2017.11.28
NYOJ(90):整数划分
*/

#include <iostream>
#include <cstring>
using namespace std;
#define N 11
unsigned long a
;/*多项式a的系数数组*/
unsigned long b
;/*多项式b的系数数组*/
unsigned long c
;/*存储多项式a*b的结果*/

/*两个多项式进行乘法,系数分别在a和b中,结果保存到c ,项最大次数到N */
/*注意这里我们只需要计算到前N项就够了。*/
void Poly()
{
int i, j;
memset(c, 0, sizeof(c));
for (i = 0; i<N; i++)
for (j = 0; j<N - i; j++) /*y<N-i: 确保i+j不会越界*/
c[i + j] += a[i] * b[j];
}

/*计算出前N项系数!即g(x,1) g(x,2)... g(x,n)的展开结果*/
void Init()
{
int i, k;
memset(a, 0, sizeof(a));
memset(c, 0, sizeof(c));
for (i = 0; i<N; i++) a[i] = 1; /*第一个多项式:g(x, 1) = x^0 + x^1 + x^2 + x^3 +  */
for (k = 2; k<N; k++)
{
memset(b, 0, sizeof(b));
for (i = 0; i<N; i += k) b[i] = 1;/*第k个多项式:g(x, k) = x^0 + x^(k) + x^(2k) + x^(3k) +  */
Poly(); /* 多项式乘法:c= a*b */
memcpy(a, c, sizeof(c)); /*把相乘的结果从c复制到a中:c=a; */
}
}

int main()
{
int M, n;
cin >> M;
while (M--)
{
cin >> n;
Init();
cout << c
<< endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息