普通型母函数
定义:
对于任意数列a0,a1,a2…an 即用如下方法与一个函数联系起来:
~G(x) = a0 + a1x + a2x*2 + a3x^3 +….+ anx^n
则称G(x)是数列的生成函数(generating function)
例子:
比较典型的是:A(x) = (1+x)^n~C(n,0),C(n,1),C(n,2),C(n,3),…..,C(n,n)
生成函数是说,构造这么一个多项式函数g(x),使得x的n次方系数为f(n)。 如:序列{0,1,2,3,4,5…n}的生成函数为:f(x)=0+x+2x^2+3x^3+4x^4+…+nx^n
生成函数最绝妙的是,某些生成函数可以化简为一个很简单的函数。也就是说,不一定每个生成函数都是用一长串多项式来表示的。比如,这个函数f(n)=1 (n当然是属于自然数的),它的生成函数就应该是g(x)=1+x+x^2+x^3+x^4+…(每一项都是一,即使n=0时也有x^0系数为1,所 以有常数项)。再仔细一看,这就是一个有无穷多项的等比数列求和嘛。如果-1
举一个例子说明:
考虑这个问题:从二班选n个MM出来有多少种选法。学过简单的排列与组合的同学都知道,答案就是C(4,n)。也就是说。从n=0开始,问题的答案分别是 1,4,6,4,1,0,0,0,…(从4个MM中选出4个以上的人来方案数当然为0喽)。那么它的生成函数g(x)就应该是g(x)=1+4x+6x^2+4x^3+x^4。这不就是……二项式展开吗?于是,g(x)=(1+x)^4。
你或许应该知道,(1+x)^k=C(k,0)x^0+C(k,1)x^1+…+C(k,k)x^k;但你或许不知道,即使k为负数和小数的时候, 也有类似的结论: (1+x)^k=C(k,0)x^0+C(k,1)x^1+…+C(k,k)x^k+C(k,k+1)x^(k+1)+C(k,k+2)x^(k+2)+…
广义的组合数C(k,i)就等于
k(k-1)(k-2)(k-i+1)/i!,比如C(4,6)=4*3*2*1*0*(-1)/6!=0,再比如C(-1.4,2)=(-1.4)*(-2.4)/2!=1.68,当k为整数时,所有i>k时的C(k,i)中分子都要“越过”0这一项,因此后面C(k,k+1),C(k,k+2)之类的都为0了,与我们的经典二项式定理结论相同;不同的是,牛顿二项式定理中的指数k可以是任意实数.
再举一个例子说明一些更复杂的生成函数。n=x1+x2+x3+…+xk有多少个非负整数解?这道题是学排列与组合的经典例题了。把每组解的每个数都 加1,就变成n+k=x1+x2+x3+…+xk的正整数解的个数了。教材上或许会出现这么一个难听的名字叫“隔板法”:把n+k个东西排成一排,在 n+k-1个空格中插入k-1个“隔板”。答案我们总是知道的,就是C(n+k-1,k-1)。它就等于C(n+k-1,n)。它关于n的生成函数是 g(x)=1/(1-x)^k。这个生成函数是怎么来的呢?其实,它就是(1-x)的-k次方,.。事实上,我们有一个纯组合数学的 更简单的解释方法。因为我们刚才的几何级数1+x+x^2+x^3+x^4+…=1/(1-x),那么 (1+x+x^2+x^3+x^4+…)^k就等于1/(1-x)^k。仔细想想k个(1+x+x^2+x^3+x^4+…)相乘是什么意思。 (1+x+x^2+x^3+x^4+…)^k的展开式中,n次项的系数就是我们的答案,因为它的这个系数是由原式完全展开后k个指数加起来恰好等于n的项合并起来得到的。
现在我们引用《组合数学》上暴经典的一个例题。很多书上都会有这类题。
我们要从苹果、香蕉、橘子和梨中拿一些水果出来,要求苹果只能拿偶数个,香蕉的个数要是5的倍数,橘子最多拿4个,梨要么不拿,要么只能拿一个。问按这样的要求拿n个水果的方案数。
结合刚才的k个(1+x+x^2+x^3+x^4+…)相乘,我们也可以算出这个问题的生成函数。
引用内容
g(x)=(1+x^2+x^4+…)(1+x^5+x^10+..)(1+x+x^2+x^3+x^4)(1+x)
半都约掉了)
=(1-x)^(-2)=C(1,0)+C(2,1)x+C(3,2)x^2+C(4,3)x^3… (参见刚才对1/(1-x)^k的展开)
=1+2x+3x^2+4x^3+5x^4+….
于是,拿n个水果有n+1种方法。我们利用生成函数,完全使用代数手段得到了答案!
1/(1-x)=1+x+x^2+x^3+x^4+…是前面说过的。我们对这个式子等号两边同时求导数。于是,1/(1-x)^2=1+2x+3x^2+4x^3+5x^4+….。;一步就得到了我们所需要的东西!不断地再求导数,我们同样可以得到刚才用复杂的牛顿二项式定理得到的那个结论。生成函数还有很多其它的处理手段,比如等式两边同时乘以、除以常数(相当于等式右边每一项乘以、除以常数),等式两边同时乘以、除以一个x(相当于等式右边的系数“移一位”),以及求微分积分等。
我们用两种方法得到了这样一个公式:1/(1-x)^n=1+C(n,1)x^1+C(n+1,2)x^2+C(n+2,3)x^3+…+C(n+k-1,k)x^k+…。这个公式非常有用,是把一个生成函数还原为数列的武器。而且还是核武器。
母函数可分为很多种,包括普通母函数、指数母函数、L级数、贝尔级数和狄利克雷级数。对每个序列都可以写出以上每个类型的一个母函数。构造母函数的目的一般是为了解决某个特定的问题,因此选用何种母函数视乎序列本身的特性和问题的类型。
这里先给出两句话,不懂的可以等看完这篇文章再回过头来看:“把组合问题的加法法则和幂级数的t的乘幂的相加对应起来”
“母函数的思想很简单—就是把离散数列和幂级数一一对应起来,把离散数列间的相互结合关系对应成为幂级数间的运算关系,最后由幂级数形式来确定离散数列的构造. “
我们首先来看下这个多项式乘法:
1.x的系数是a1,a2,…an 的单个组合的全体。
2. x2的系数是a1,a2,…a2的两个组合的全体。
………
n. xn的系数是a1,a2,….an的n个组合的全体(只有1个)。
由此得到:如有图
母函数的定义:
对于序列a0,a1,a2,…构造一函数:
:母函数详解
图三
称函数G(x)是序列a0,a1,a2,…的母函数
G( x ) = a[0] + a[1] * x + a[2]* x^2 + ······
这里先给出2个例子,等会再结合题目分析:第一种:
有1克、2克、3克、4克的砝码各一 枚,能称出哪几种重量?每种重量各有几种可能方案?
考虑用母函数来解决这个问题:
我们假设x表示砝码,x的指数表示砝码的重量,这样:
1个1克的砝码可以用函数1+x表示,
1个2克的砝码可以用函数1+x∧2表示,
1个3克的砝码可以用函数1+x∧3表示,
1个4克的砝码可以用函数1+x∧4表示,
我们拿1+x来说,前面已经说过,x表示砝码,x的指数表示砝码的重量!即这里就是一个质量为2的砝码,那么前面的1表示什么?按照上面的理解,1其实应该写为:1*x^0,即1代表重量为2的砝码数量为0个。(理解!)
“把组合问题的加法法则和幂级数的t的乘幂的相加对应起来“
1+x表示了两种情况:1表示质量为2的砝码取0个的情况,x表示质量为2的砝码取1个的情况。这里说下各项系数的意义:
在x前面的系数a表示相应质量的砝码取a个,而1就表示相应砝码取0个,这里可不能简单的认为相应砝码取0个就该是0*x(想下为何?结合数学式子)。
所以,前面说的那句话的意义大家可以理解了吧?几种砝码的组合可以称重的情况,可以用以上几个函数的乘积表示:
(1+x)(1+x∧2)(1+x∧3)(1+x∧4)
= (1+x+x+x)(1+x+x+x)
=1+x+x+2x+2x+2x+2x+2x+x+x+x
从上面的函数知道:可称出从1克到10克,系数便是方案数。(!!!经典!!!)
例如右端有2x项,即称出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分的邮票贴出不同数值的方案数:
大家把这种情况和第一种比较有何区别?第一种每种是一个,而这里每种是无限的。
G( x ) = ( 1 + x + x^2 +····) * (1 + x^2 + x^4 +····)* (1 + x^3 + x^6 +·····)
母函数详解
以展开后的x为例,其系数为4,即4拆分成1、2、3之和的拆分数为4;
即 :4=1+1+1+1=1+1+2=1+3=2+2
这里再引出两个概念整数拆分和拆分数:
所谓整数拆分即把整数分解成若干整数的和(相当于把n个无区别的球放到n个无标志的盒子,盒子允许空,也允许放多于一个球)。
整数拆分成若干整数的和,办法不一,不同拆分法的总数叫做拆分数。
现在以上面的第二种情况每种种类个数无限为例,给出模板:
// Author: Tanky Woo
// 母函数详解
G( x ) = ( 1 + x + x^2 +····) * ( 1 + x^2 + x^4 + ····) * ( 1 + x^3 + x^6)
母函数详解
ci dao ti wei gei chu mei zhong fa ma you duo shao ge
#include
using namespace std;
const int _max = 10001;
// c1是保存各项质量砝码可以组合的数目
// c2是中间量,保存每一次的情况
int c1[_max], c2[_max];
int main()
{ //int n,i,j,k;
int nNum; //
int i, j, k;
while(cin >> nNum)
{
for(i=0; i<=nNum; ++i) // —- ①
{
c1[i] = 1;
c2[i] = 0;
}
for(i=2; i<=nNum; ++i) // —– ②// bie wang le i*i
我们来解释下上面标志的各个地方:
① 、首先对c1初始化,由第一个表达式(1+x+x2+..xn)初始化,把质量从0到n的所有砝码都初始化为1.
② 、 i从2到n遍历,这里i就是指第i个表达式,上面给出的第二种母函数关系式里,每一个括号括起来的就是一个表达式。
③、j 从0到n遍历,这里j就是只一个表达式里第j个变量,比如在第二个表达式里:(1+x2+x4….)里,第j个就是x2*j.
③ k表示的是第j个指数,所以k每次增i(因为第i个表达式的增量是i)。
④ 、把c2的值赋给c1,而把c2初始化为0,因为c2每次是从一个表达式中开始的
( 最外层,记录它正在与第几个多项式相乘。第二层,表示c1中的每一项,第三层表示后面被乘多项式中的每一项。)
以下两题是相似题注意区别
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 8280 Accepted Submission(s): 3713
Problem Description
We all know that Bin-Laden is a notorious terrorist, and he has disappeared for a long time. But recently, it is reported that he hides in Hang Zhou of China!
“Oh, God! How terrible! ”
Don’t be so afraid, guys. Although he hides in a cave of Hang Zhou, he dares not to go out. Laden is so bored recent years that he fling himself into some math problems, and he said that if anyone can solve his problem, he will give himself up!
Ha-ha! Obviously, Laden is too proud of his intelligence! But, what is his problem?
“Given some Chinese Coins (硬币) (three kinds– 1, 2, 5), and their number is num_1, num_2 and num_5 respectively, please output the minimum value that you cannot pay with given coins.”
You, super ACMer, should solve the problem easily, and don’t forget to take $25000000 from Bush!
Input
Input contains multiple test cases. Each test case contains 3 positive integers num_1, num_2 and num_5 (0<=num_i<=1000). A test case containing 0 0 0 terminates the input and this test case is not to be processed.
Output
Output the minimum positive value that one cannot pay with given coins, one line for one case.
Sample Input
1 1 3 0 0 0
Sample Output
4
Author
lcy
/题意:给你面值是1,2,5的硬币的数量,要你求由这些硬币不能组成的最小的金额。。
下面给出3种方法;
//方法1:很明显母函数
//我这里一步一步的求。。
//下面是我的一点理解。。如果叫你写由面值1,2,5的硬币所组成的金额的母函数
//Y=(1+x^2+x^3+x^4…+x^n1*1)*(1+x^2+x^4+x^6…x^n2*2)*(1+x^5+x^10+…x^n3*5)
#include
#include
#define MAX 10010
int num[3];
int val[3]={1,2,5};
int n;
int c1[MAX],c2[MAX];
int main( )
{
while(scanf("%d%d%d",&num[0],&num[1],&num[2]),num[0]||num[1]||num[2])
{
int i,j,k,t;
n=num[0]*1+num[1]*2+num[2]*5;// num[0]*val[0]+num[1]*val[1]+num[2]*val[3] budui
memset(c1,0,sizeof(c1));
memset(c2,0,sizeof(c2));
for( i=0;i<=num[0];i+=val[0])
{
c1[i]=1;
}
for( i=1;i<=2;i++)
{
for( j=0;j<=n;j++)
for( k=0;k<=num[i]*val[i]&&k+j<=n;k+=val[i])
c2[j+k]+=c1[j];
for(t=0;t<=n;t++)
{
c1[t]=c2[t];
c2[t]=0;
}
}
for(i=0;i<=n+1;i++)
if(c1[i]==0)
{
printf("%d\n",i);
break;
}
}
return 0;
}
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 10995 Accepted Submission(s): 3827
Problem Description
Nowadays, we all know that Computer College is the biggest department in HDU. But, maybe you don’t know that Computer College had ever been split into Computer College and Software College in 2002.
The splitting is absolutely a big event in HDU! At the same time, it is a trouble thing too. All facilities must go halves. First, all facilities are assessed, and two facilities are thought to be same if they have the same value. It is assumed that there is N (0
Input
Input contains multiple test cases. Each test case starts with a number N (0 < N <= 50 — the total number of different facilities). The next N lines contain an integer V (0
Output
For each case, print one line containing two integers A and B which denote the value of Computer College and Software College will get respectively. A and B should be as equal as possible. At the same time, you should guarantee that A is not less than B.
Sample Input
2 10 1 20 1 3 10 1 20 2 30 1 -1
Sample Output
20 10 40 40
题意:
给你n种物品,每种物品的价值,以及数量告诉你,
让你把它们尽可能的平分,但不能使输出的前一个数小于第二个,
小于0即停止执行
#include
#include
int main( )
{
int m,n;
int i,j,k,t;
while(scanf("%d",&m)==1)
{
if(m<0) break;
n=0;
int val[m],num[m];//neng fang zhi shu zhu yue jian
for( i=0;i0;i--)
{
if(c1[i]!=0)
break;
}
printf("%d %d\n",n-i,i);
}
return 0;
}
Crawling in process… Crawling failed Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
Description
Input
The last line of the input file will be “0 0 0 0 0 0”; do not process this line.
Output
Output a blank line after each test case.
Sample Input
Sample Output
有分别价值为1,2,3,4,5,6的6种物品,输入6个数字,表示相应价值的物品的数量,问一下能不能将物品分成两份,是两份的总价值相等,其中一个物品不能切开,只能分给其中的某一方,当输入六个0是(即没有物品了),这程序结束,总物品的总个数不超过20000
#include
#include
#define N 20000
int c[N];
int num[7];
int p;
int main( )
{
int i,j,k,t=0;
while(scanf("%d%d%d%d%d%d",&num[1],&num[2],&num[3],&num[4],&num[5],&num[6]),num[1]||num[2]||num[3]||num[4]||num[5]||num[6])
{
for(i=1;i<=6;i++)
{
num[i]%=10; //(取到最后发现对10取余就好了,多了感觉没有什么用!)
}
p=1*num[1]+2*num[2]+3*num[3]+4*num[4]+5*num[5]+6*num[6];
memset(c,0,sizeof(c));
printf("Collection #%d:\n",++t);
if(p%2)
{
printf("Can’t be divided.\n");
}
else{
c[0]=1;
p/=2;
for( i=1;i<=6;i++)
{
for( j=p;j>=0;j--)
for( k=1;k<=num[i]&&j+k*i<=p;k++)//从大到小
c[j+k*i]|=c[j];//(存在性的判断)
}
if(c[p])
printf("Can be divided.\n");
else
printf("Can’t be divided.\n");
}
puts("");
}
}