ACM数论之旅13---母函数(又叫生成函数)(痛并快乐着(╭ ̄3 ̄)╭)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ACM数论之旅13---母函数(又叫生成函数)(痛并快乐着(╭ ̄3 ̄)╭)相关的知识,希望对你有一定的参考价值。

 

(前排出售零食瓜子)

前言:(????不看会吃亏的)

接下来要讲的算法比较难,一般人听不懂,因为你不能用常人的思想去理解

就像高数(说多了都是泪( >﹏<。))

你要用常规方法去想肯定很累( ̄▽ ̄)~*

有时候一直半解的多读几遍反而高效

就像矩阵,发明矩阵的人是天才,我们只能在使用矩阵的同时一直感叹:“哇!好神奇!这样也可以!”

而不是先研究为什么他会有这么多神奇的性质

因为,毕竟从发明者角度来说,他就是考虑了这么多才创造出了神奇的矩阵

而如果矩阵的每一个性质你都一点点研究过去,终有一天,你也可以像他一样对矩阵充分了解,但是时间太漫长了

所以,有时候,你只要先学会用矩阵的性质就可以了,然后在某一天,说不定,你就了解了它的原理(ㄒoㄒ)/

 

简而言之就是,我接下来讲的东西,能懂就懂,不懂就先记着

 

 

 

 

 

 

 

 

 

生成函数即母函数,是组合数学中尤其是计数方面的一个重要理论和工具。

但是ACM中的母函数木有像数学那么深究,应用的都是母函数的一些基本

(就好比方程的配方,因式的分解,写起来容易,你用电脑写起来就麻烦了,所以学计算机就不要老跟数学家瞎闹( ̄3 ̄))

 

 

什么是母函数

就是把一个已知的序列和x的多项式合并起来,新产生的多项式就叫原来序列的母函数

 

至于怎么合并,看这个例子

 

序列{0,1,2,3,4,5...n}的母函数就是

f(x)=0+x+2x^2+3x^3+4x^4+...+nx^n(这个x没有任何意义,应该说,你不需要把它当做一个函数,你只要知道母函数这么写就可以了)

 

序列{1,1,1,1,1......}的母函数就是

f(x)=1+x+x^2+x^3+x^4....

 

二项式展开的序列比如这个{1,4,6,4,1,0,0,0,0,0.....}是C(4,0)到C(4,4)的系数,那它的母函数就是

f(x)=1+4x+6x^2+4x^3+1x^4

 

母函数就长这样,对正常人来讲,这种东西毫无意义( ° △ °|||)

 

 

 

 

 

 

 

 

 

 

 

那看点有意义的东西(以下都是经典题型,我从杭电ACM课件抄来的)

 

有1克、2克、3克、4克的砝码各一枚,能称出哪几种重量?每种重量各有几种可能方案?

假如x的幂次数表示几克的砝码

那么

1克的砝码表示为1+x^1

2克的砝码表示为1+x^2

3克的砝码表示为1+x^3

4克的砝码表示为1+x^4

 

每个砝码都可以选择取或不取

所以这里的1可以认为1*x^0,表示不取这颗砝码

 

那么把这些乘起来

(1+x^1)(1+x^2)(1+x^3)(1+x^4)

=1+(x^1)+(x^2)+2(x^3)+2(x^4)+2(x^5)+2(x^6)+2(x^7)+(x^8)+(x^9)+(x^10)

 

根据指数来看,我们可以称出0~10这么多的重量,其中3~7的系数为2,说明有2种称的方法

那么我们来细看一遍

0:(什么砝码都不放).......................(1种)

1:1.............................................(1种)

2:2.............................................(1种)

3:3或1+2.....................................(2种)

4:4或1+3.....................................(2种)

5:1+4或2+3.................................(2种)

6:2+4或1+2+3..............................(2种)

7:3+4或1+2+4..............................(2种)

8:1+3+4......................................(1种)

9:2+3+4......................................(1种)

10:1+2+3+4.................................(1种)

 

分毫不差(???*)

所以说母函数在ACM就是这么用的,跟函数没关系,跟写法有关系。。。

 

 

 

 

 

再来一题

求用1分、2分、3分的邮票贴出不同数值的方案数:(每张邮票的数量是无限的)

那么

1分:(1+x^1+x^2+x^3+x^4+......)

2分:(1+x^2+x^4+x^6+x^8+......)

3分:(1+x^3+x^6+x^9+x^12+......)

然后这3个乘起来(让电脑去乘吧)

 

对于这种无限的,题目肯定会给你他询问的数值的范围,计算到最大的范围就可以了

 

 

附代码:

 1 #include<cstdio>
 2 typedef long long LL;
 3 const int N = 100 + 5;//假如题目只问到100为止 
 4 const int MAX = 3;//题目只有1,2,3这3种邮票 
 5 LL c1[N], c2[N];//c2是临时合并的多项式,c1是最终合并的多项式 
 6 int n;
 7 void init(){
 8     for(int i = 0; i < N; i ++) c1[i] = 1;//1分的邮票
 9     for(int i = 2; i <= MAX; i ++){//把2分到MAXN的邮票合并,变成一个多项式 
10         for(int j = 0; j < N; j += i){//i分的邮票,步长是i
11             for(int k = 0; j + k < N; k ++){//从x^0到x^N遍历一遍 
12                 c2[j + k] += c1[k];//因为j的所有项系数为1,所以c1[k]可以看成c1[k]*1; 
13             }
14         } 
15         for(int j = 0; j < N; j ++){//把c2的数据抄到c1,清空c2 
16             c1[j] = c2[j];
17             c2[j] = 0;
18         }
19     }
20 } 
21 int main(){
22     init();
23     while(scanf("%d", &n) != EOF){
24         printf("%I64d\n", c1[n]);
25     }
26 }

 

 

 

 

我们就来把这个模板用于实际吧

hdu 1028

http://acm.hdu.edu.cn/showproblem.php?pid=1028

题目问一个数字n能够拆成多少种数字的和

比如n=4

  4 = 4;
  4 = 3 + 1;
  4 = 2 + 2;
  4 = 2 + 1 + 1;
  4 = 1 + 1 + 1 + 1;

有5种,那么答案就是5

 

AC代码:

技术分享
 1 #include<cstdio>
 2 typedef long long LL;
 3 const int N = 120 + 5; 
 4 const int MAX = 120 + 5; 
 5 LL c1[N], c2[N]; 
 6 int n;
 7 void init(){
 8     for(int i = 0; i < N; i ++) c1[i] = 1;
 9     for(int i = 2; i <= MAX; i ++){ 
10         for(int j = 0; j < N; j += i){
11             for(int k = 0; j + k < N; k ++){ 
12                 c2[j + k] += c1[k]; 
13             }
14         } 
15         for(int j = 0; j < N; j ++){ 
16             c1[j] = c2[j];
17             c2[j] = 0;
18         }
19     }
20 } 
21 int main(){
22     init();
23     while(scanf("%d", &n) != EOF){
24         printf("%I64d\n", c1[n]);
25     }
26 }
View Code

 

 

再来,hdu 1398

http://acm.hdu.edu.cn/showproblem.php?pid=1398

题目说一个国家的硬币都是方形的,面值也是方形的

有1块钱,4块钱,9块钱,16块钱......一直到289块钱(17^2)

问想组成n块钱有几种方法

 

AC代码:

技术分享
 1 #include<cstdio>
 2 typedef long long LL;
 3 const int N = 300 + 5; 
 4 const int MAX = 17; 
 5 LL c1[N], c2[N]; 
 6 int n;
 7 void init(){
 8     for(int i = 0; i < N; i ++) c1[i] = 1;
 9     for(int i = 2; i <= MAX; i ++){ 
10         for(int j = 0; j < N; j += i*i){
11             for(int k = 0; j + k < N; k ++){ 
12                 c2[j + k] += c1[k]; 
13             }
14         } 
15         for(int j = 0; j < N; j ++){ 
16             c1[j] = c2[j];
17             c2[j] = 0;
18         }
19     }
20 } 
21 int main(){
22     init();
23     while(scanf("%d", &n) != EOF && n){
24         printf("%I64d\n", c1[n]);
25     }
26 }
View Code

 

都是改一些小地方,都是模板题(o?ω?o)

 

 

 

 

 

 

 

 

 

 

那么ACM的母函数讲完了(*。∀。)

之后是数学上的母函数,不想看的人就可以结束本章内容了(*。∀。)

 

以上是关于ACM数论之旅13---母函数(又叫生成函数)(痛并快乐着(╭ ̄3 ̄)╭)的主要内容,如果未能解决你的问题,请参考以下文章

acm数论之旅--中国剩余定理

ACM数论之旅9---中国剩余定理(壮哉我大中华╰(*°▽°*)╯)

生成函数(母函数)入门详解

普通母函数简单使用

ACM数论之旅4---扩展欧几里德算法(欧几里德(???)?是谁?)

2189 ACM 母函数 素数