HDU 1028 Ignatius and the Princess III(母函数)
Ignatius and the Princess III
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 15794 Accepted Submission(s): 11138
Description
"Well, it seems the first problem is too easy. I will let you know how foolish you are later." feng5166 says.
"The second problem is, given an positive integer N, we define an equation like this:
N=a[1]+a[2]+a[3]+...+a[m];
a[i]>0,1<=m<=N;
My question is how many different equations you can find for a given N.
For example, assume N is 4, we can find:
4 = 4;
4 = 3 + 1;
4 = 2 + 2;
4 = 2 + 1 + 1;
4 = 1 + 1 + 1 + 1;
so the result is 5 when N is 4. Note that "4 = 3 + 1" and "4 = 1 + 3" is the same in this problem. Now, you do it!"
"The second problem is, given an positive integer N, we define an equation like this:
N=a[1]+a[2]+a[3]+...+a[m];
a[i]>0,1<=m<=N;
My question is how many different equations you can find for a given N.
For example, assume N is 4, we can find:
4 = 4;
4 = 3 + 1;
4 = 2 + 2;
4 = 2 + 1 + 1;
4 = 1 + 1 + 1 + 1;
so the result is 5 when N is 4. Note that "4 = 3 + 1" and "4 = 1 + 3" is the same in this problem. Now, you do it!"
Input
The
input contains several test cases. Each test case contains a positive
integer N(1<=N<=120) which is mentioned above. The input is
terminated by the end of file.
Output
For each test case, you have to output a line contains an integer P which indicate the different equations you have found.
Sample Input
4
10
20
Sample Output
5
42
627
Analysis
这是一道基础的母函数题
这一题就是算出 ( x^0 + x^1 + x^2 + ...)( x^0 + x^2 + x^4 + ...)( x^0 + x^3 + x^6 + ...) ...
如第一个括号中的 x^0 代表取0个1, x^2 代表取2个1, 价值 2*1 = 1
第二个括号中的 x^0 代表取0个2, x^4 代表取2个2, 价值 2*2 = 4
指数代表取了之后的价值和
最后的展开式中某一项 a*x^b 代表 价值(总和)为 b 时有 a 种取法
#include <cstdio> #include <cstring> int c1[125],c2[125]; // c1[i] 表示指数为i的x的系数 即 a*x^3 中的a // c2[i] 表示两个因子相乘指数和为i时,乘积的系数 如 3*x^4 * x^5 = 3 * x^9 后面的3就是c2[9] int main() { int n; int i,j,k; while(~scanf("%d",&n)) { for(i=0;i<=n;i++) // 可以看做计算第一个括号 ( x^0 + x^1 + x^2 + ...) 每一项系数为1 { c1[i] = 1; c2[i] = 0; } for(i=2;i<=n;i++) // 计算 (前面已计算过的括号所累乘得到的 大大的括号)*(后面一个括号) { // 第一次循环就是计算 ( x^0 + x^1 + x^2 + ...)*( x^0 + x^2 + x^4 + ...) // 第二次循环计算 ( x^0 + x^1 + x^2 + x^3 + 2 * x^4 + x^5 + x^6 + ...)*( x^0 + x^3 + x^6 + ...) for(j=0;j<=n;j++) // j代表前一个括号里的每一项 for(k=0;k+j<=n;k+=i) // k代表后一个括号里的每一项 { c2[k+j] += c1[j]; // 用c2来保存乘得的结果 因为后一个括号中每一项的系数一定是1,所以可以直接 += } for(j=0;j<=n;j++) // 计算完毕后将两个括号合并成的大大括号中每一项的系数保存在c1中,c2置空 { c1[j] = c2[j]; c2[j] = 0; } } printf("%d\n",c1[n]); } }