数论——拆分数++母函数模版
2012-11-10 18:13
190 查看
首先,我们引进一个小小概念来方便描述吧,record
[m]是把自然数划分成所有元素不大于m的分法,例如:
当n=4,m=1时,要求所有的元素都比m小,所以划分法只有1种:{1,1,1,1};
当n=4,m=2时,。。。。。。。。。。。。。。。。只有3种{1,1,1,1},{2,1,1},{2,2};
当n=4,m=3时,。。。。。。。。。。。。。。。。只有4种{1,1,1,1},{2,1,1},{2,2},{3,1};
当n=4,m=5时,。。。。。。。。。。。。。。。。只有5种{1,1,1,1},{2,1,1},{2,2},{3,1},{4};
从上面我们可以发现:当n==1||m==1时,只有一种分法;
当n<m时,由于分法不可能出现负数,所以record
[m]=record
;
当n==m时,那么就得分析是否要分出m这一个数,如果要分那就只有一种{m},要是不分,那就是把n分成不大于m-1的若干份;即record
=1+record
[n-1];
当n>m时,那么就得分析是否要分出m这一个数,如果要分那就{{m},{x1,x2,x3..}}时n-m的分法record[n-m][m],要是不分,那就是把n分成不大于m-1的若干份;即record
[m]=record[n-m][m]+record
[m-1];
那么其递归式:
record
[m]= 1 (n==1||m==1)
record
(n<m)
1+record
[m-1] (n==m)
record[n-m][m]+record
[m-1] (N>m)
——————————————————————————————————————————
把加法变为幂运算
这里先给出2个例子,等会再结合题目分析:
第一种:
有1克、2克、3克、4克的砝码各一 枚,能称出哪几种重量?每种重量各有几种可能方案?
考虑用母函数来接吻这个问题:
我们假设x表示砝码,x的指数表示砝码的重量,这样:
1个1克的砝码可以用函数1+x表示,
1个2克的砝码可以用函数1+x2表示,
1个3克的砝码可以用函数1+x3表示,
1个4克的砝码可以用函数1+x4表示,
上面这四个式子懂吗?
我们拿1+x2来说,前面已经说过,x表示砝码,x的指数表示重量,即这里就是一个质量为2的砝码,那么前面的1表示什么?1代表重量为2的砝码数量为0个。(理解!)
不知道大家理解没,我们这里结合前面那句话:
“把组合问题的加法法则和幂级数的t的乘幂的相加对应起来”
1+x2表示了两种情况:1表示质量为2的砝码取0个的情况,x2表示质量为2的砝码取1个的情况。
这里说下各项系数的意义:
在x前面的系数a表示相应质量的砝码取a个,而1就表示相应砝码取0个,这里可不能简单的认为相应砝码取0个就该是0*x2(想下为何?结合数学式子)。
所以,前面说的那句话的意义大家可以理解了吧?
几种砝码的组合可以称重的情况,可以用以上几个函数的乘积表示:
(1+x)(1+x2)(1+x3)(1+x4)
=(1+x+x2+x3)(1+x3+x4+x7)
=1+x+x2+2x3+2x4+2x5+2x6+2x7+x8+x9+x10
从上面的函数知道:可称出从1克到10克,系数便是方案数。(!!!经典!!!)
例如右端有2x5 项,即称出5克的方案有2:5=3+2=4+1;同样,6=1+2+3=4+2;10=1+2+3+4。
故称出6克的方案有2,称出10克的方案有1 。
接着上面,接下来是第二种情况:
求用1分、2分、3分的邮票贴出不同数值的方案数:
大家把这种情况和第一种比较有何区别?第一种每种是一个,而这里每种是无限的。
以展开后的x4为例,其系数为4,即4拆分成1、2、3之和的拆分数为4;
即 :4=1+1+1+1=1+1+2=1+3=2+2
这里再引出两个概念整数拆分和拆分数(没有顺序):
所谓整数拆分即把整数分解成若干整数的和(相当于把n个无区别的球放到n个无标志的盒子,盒子允许空,也允许放多于一个球)。
整数拆分成若干整数的和,办法不一,不同拆分法的总数叫做拆分数。
母函数模版/article/5479354.html
[m]是把自然数划分成所有元素不大于m的分法,例如:
当n=4,m=1时,要求所有的元素都比m小,所以划分法只有1种:{1,1,1,1};
当n=4,m=2时,。。。。。。。。。。。。。。。。只有3种{1,1,1,1},{2,1,1},{2,2};
当n=4,m=3时,。。。。。。。。。。。。。。。。只有4种{1,1,1,1},{2,1,1},{2,2},{3,1};
当n=4,m=5时,。。。。。。。。。。。。。。。。只有5种{1,1,1,1},{2,1,1},{2,2},{3,1},{4};
从上面我们可以发现:当n==1||m==1时,只有一种分法;
当n<m时,由于分法不可能出现负数,所以record
[m]=record
;
当n==m时,那么就得分析是否要分出m这一个数,如果要分那就只有一种{m},要是不分,那就是把n分成不大于m-1的若干份;即record
=1+record
[n-1];
当n>m时,那么就得分析是否要分出m这一个数,如果要分那就{{m},{x1,x2,x3..}}时n-m的分法record[n-m][m],要是不分,那就是把n分成不大于m-1的若干份;即record
[m]=record[n-m][m]+record
[m-1];
那么其递归式:
record
[m]= 1 (n==1||m==1)
record
(n<m)
1+record
[m-1] (n==m)
record[n-m][m]+record
[m-1] (N>m)
——————————————————————————————————————————
把加法变为幂运算
这里先给出2个例子,等会再结合题目分析:
第一种:
有1克、2克、3克、4克的砝码各一 枚,能称出哪几种重量?每种重量各有几种可能方案?
考虑用母函数来接吻这个问题:
我们假设x表示砝码,x的指数表示砝码的重量,这样:
1个1克的砝码可以用函数1+x表示,
1个2克的砝码可以用函数1+x2表示,
1个3克的砝码可以用函数1+x3表示,
1个4克的砝码可以用函数1+x4表示,
上面这四个式子懂吗?
我们拿1+x2来说,前面已经说过,x表示砝码,x的指数表示重量,即这里就是一个质量为2的砝码,那么前面的1表示什么?1代表重量为2的砝码数量为0个。(理解!)
不知道大家理解没,我们这里结合前面那句话:
“把组合问题的加法法则和幂级数的t的乘幂的相加对应起来”
1+x2表示了两种情况:1表示质量为2的砝码取0个的情况,x2表示质量为2的砝码取1个的情况。
这里说下各项系数的意义:
在x前面的系数a表示相应质量的砝码取a个,而1就表示相应砝码取0个,这里可不能简单的认为相应砝码取0个就该是0*x2(想下为何?结合数学式子)。
所以,前面说的那句话的意义大家可以理解了吧?
几种砝码的组合可以称重的情况,可以用以上几个函数的乘积表示:
(1+x)(1+x2)(1+x3)(1+x4)
=(1+x+x2+x3)(1+x3+x4+x7)
=1+x+x2+2x3+2x4+2x5+2x6+2x7+x8+x9+x10
从上面的函数知道:可称出从1克到10克,系数便是方案数。(!!!经典!!!)
例如右端有2x5 项,即称出5克的方案有2:5=3+2=4+1;同样,6=1+2+3=4+2;10=1+2+3+4。
故称出6克的方案有2,称出10克的方案有1 。
接着上面,接下来是第二种情况:
求用1分、2分、3分的邮票贴出不同数值的方案数:
大家把这种情况和第一种比较有何区别?第一种每种是一个,而这里每种是无限的。
以展开后的x4为例,其系数为4,即4拆分成1、2、3之和的拆分数为4;
即 :4=1+1+1+1=1+1+2=1+3=2+2
这里再引出两个概念整数拆分和拆分数(没有顺序):
所谓整数拆分即把整数分解成若干整数的和(相当于把n个无区别的球放到n个无标志的盒子,盒子允许空,也允许放多于一个球)。
整数拆分成若干整数的和,办法不一,不同拆分法的总数叫做拆分数。
母函数模版/article/5479354.html
//made by syx //time 2010年9月11日 10:17:27 //母函数例题 /*//整数拆分模板 #include <iostream> using namespace std; const int lmax=10000; //c1是用来存放展开式的系数的,而c2则是用来计算时保存的, //他是用下标来控制每一项的位置,比如 c2[3] 就是 x^3 的系数。 //用c1保存,然后在计算时用c2来保存变化的值。 int c1[lmax+1],c2[lmax+1]; int main() { int n, i, j, k ; // 计算的方法还是模拟手动运算,一个括号一个括号的计算, // 从前往后 while ( cin>>n ){ //对于 1+x+x^2+x^3+ 他们所有的系数都是 1 // 而 c2全部被初始化为0是因为以后要用到 c2[i] += x ; for ( i=0; i<=n; i++ ){ c1[i]=1; c2[i]=0; } //第一层循环是一共有 n 个小括号,而刚才已经算过一个了 //所以是从2 到 n for (i=2; i<=n; i++){ // 第二层循环是把每一个小括号里面的每一项,都要与前一个 //小括号里面的每一项计算。 for ( j=0; j<=n; j++ ) //第三层小括号是要控制每一项里面 X 增加的比例 // 这就是为什么要用 k+= i ; for ( k=0; k+j<=n; k+=i ){ // 合并同类项,他们的系数要加在一起,所以是加法,呵呵。 // 刚开始看的时候就卡在这里了。 c2[ j+k] += c1[ j]; } // 刷新一下数据,继续下一次计算,就是下一个括号里面的每一项。 for ( j=0; j<=n; j++ ){ c1[j] = c2[j] ; c2[j] = 0 ; } } cout<<c1 <<endl; } return 0; } 这句 c2[j+k] += c1[j];的理解还要自己好好的体会体会啊! */ 自己理解:对于(#式) (1+x+x^2+x^3+x^4+x^5+....)*(1+x^2+x^4+x^6+x^8+x^10+....)*(1+x^3+x^6+x^9+x^12....)..... 第一个for给c1 和 c2 赋值,把上面#式的第一个括号(1+x+x^2+x^3+x^4+x^5+....)的系数给放在c1中, 从而再次计算从 # 的第二个括号开始, 所以 i 就是代表的# 式第几个括号, 而 用程序模拟手工计算,就是先计算第一个括号与第二个括号计算,把结果放到c2中, 在把结果与第三个括号计算,把结果放到c2中,在和第四个括号计算,........ 所以 j 就是指的已经计算出的各项的系数 ,比如第一次之后 1+x+x^2+x^3+x^4+x^5+... , j=0指向1 , j=2 指向x , .... ,而 k 就是指将要计算的那个括号中的项,因为第i个括号,中的指数为0 , i , 2i....所以 k要 + i ; 而结果 c2[j+k] += c1[j]; 就是把以计算出的 j项的系数和现在正在计算的括号的k项相乘,所以指数为j+k ,所以结果放到c2[j+k] 中 ,这就是这几个for的作用! 最后刷新下结果,下一组数据计算! //整数拆分母函数模板 #include <iostream> using namespace std; const int lmax=10000; int c1[lmax+1],c2[lmax+1]; int main() { int n,i,j,k; while (cin>>n) { //首先对c1初始化,由第一个表达式(1+x+x2+..xn)初始化, //把质量从0到n的所有砝码都初始化为1. for (i=0;i<=n;i++) { c1[i]=1; c2[i]=0; } //i从2到n遍历,这里i就是指第i个表达式, //上面给出的第二种母函数关系式里,每一个括号括起来的就是一个表达式。 for (i=2;i<=n;i++) { //j 从0到n遍历,这里j就是只一个表达式 //里第j个变量,比如在第二个表达式里:(1+x2+x4….)里,第j个就是x2*j. for ( j=0;j<=n;j++) for (k=0;k+j<=n;k+=i)//k表示的是第j个指数,所以k每次增i(因为第i个表达式的增量是i)。 c2[ j+k]+=c1[j]; //把c2的值赋给c1,而把c2初始化为0,因为c2每次是从一个表达式中开始的 for (j=0;j<=n;j++) { c1[j]=c2[j]; c2[j]=0; } } cout<<c1 <<endl; } return 0; }
相关文章推荐
- HDU 2069 母函数模版题
- UVA 10976 分数拆分(数论+枚举)
- ACM数论模版
- poj 3696 The Luckiest number——数论 (快速幂取模,乘法取模模版)
- 母函数模版详解和示例
- hdu 1028 母函数模版
- HDU 2069 母函数模版题
- 51nod 1189 阶乘分数 [因子个数+逆元]【数论】
- 母函数入门【模版】
- HDU 2069 母函数模版题
- Astronomy poj 3101 数论 分数的最小公倍数 Cherish the memory of my broken heart
- 数论小模版解题报告
- HDU 2069 母函数模版题
- hrbust 1178 分数加减(模拟+数论gcd,lcm)
- 对 质数筛法 和 质因数分解 的模版实验 - 数论
- 数论模版-欧拉函数、莫比乌斯函数和素数
- HDU 2069 母函数模版题
- 母函数大模版
- (Relax 数论 1.17)POJ 3101 Astronomy(分数的最小公倍数)
- 基础母函数模版