zoukankan      html  css  js  c++  java
  • 母函数及其应用+模板

    部分摘自这位大佬的博客https://www.cnblogs.com/linyujun/p/5207730.html

    生成函数即母函数,是组合数学中尤其是计数方面的一个重要理论和工具。 最早提出母函数的人是法国数学家LaplaceP.S.在其1812年出版的《概率的分析理论》中明确提出“生成函数的计算”。 生成函数的应用简单来说在于研究未知(通项)数列规律,用这种方法在给出递推式的情况下求出数列的通项。 

    在这里我们不去高深地研究数学上母函数,而是讲讲简单的母函数应用。

    1.母函数引入

    就是把一个已知的序列和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

    这些东西对于我们来说并没有说明意义,母函数对我们来说只是一个工具,是一个载体,那来看看母函数是怎么样装载数据的吧!

    例1:若有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就是这么用的,跟函数没关系,跟写法有关系。

    例2:求用1分、2分、3分的邮票贴出不同数值的方案数,每种邮票可以有无限张。

    因邮票允许重复,故母函数为:

    对于这种连续相乘,我们人类是很讨厌的,但对于计算机这种重复运算是很轻松的,我们只要将我们解多项式的思路带进去即可。

    2.代码说明

    我们首先知道对于最后得到的那一个母函数,系数代表的是方案数,而指数代表的是组成的数值,运算过程就是多项式的乘法。而两个多次方程的乘法,运算无非是系数相乘,指数相加,仅仅是这个方程的两个信息的运算。那能不能用什么数据结构直接表示出一个对象的这个两个信息呢?首先想到的可能是结构体,结构体可以用来表示一个对象的多个信息,但是运算繁琐;其实用数组就可以了,下标代表组成的数值,数组取值代表方案数!!!

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

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #define MAX 310
     6 int a[MAX];///最终合并的多项式
     7 int b[MAX];///临时合并用的多项式
     8 int n;
     9 const int N=110;
    10 using namespace std;
    11 void init()
    12 {
    13     int i,j,k;
    14     a[0]=1;///一开始的0的情况
    15     for (i=1; i<=3; i++)///代表1分,2分,3分三个多项式的合并
    16     {
    17         for (j=0; j<N; j+=i)///i分的邮票,步长为i
    18         {
    19             for (k=0; k+j<N; k++)///从x^0到x^N遍历一遍
    20             {
    21                 b[j+k]+=a[j];///核心
    22             }
    23         }
    24         for (j=0; j<N; j++)///b中数据抄到a,b清空
    25         {
    26             a[j]=b[j];
    27             b[j]=0;
    28         }
    29     }
    30 }
    31 int main()
    32 {
    33     int i,j,k;
    34     init();
    35     while(scanf("%d",&n)!=EOF)
    36     {
    37         printf("%d
    ",a[n]);
    38     }
    39     return 0;
    40 }

    b.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

    其实这个题就可以转换成使用1~N个数,每个数可以多次使用,能组成的数有多少种方案?

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #define MAX 130
     6 #define N 130
     7 #define ll long long int
     8 ll a[MAX];
     9 ll b[MAX];
    10 int n;
    11 using namespace std;
    12 void init()
    13 {
    14     int i,j,k;
    15     a[0]=1;
    16     for (i=1; i<=MAX; i++)
    17     {
    18         for (j=0; j<N; j+=i)
    19         {
    20             for (k=0; k+j<N; k++)
    21             {
    22                 b[j+k]+=a[k];
    23             }
    24         }
    25         for (j=0; j<N; j++)
    26         {
    27             a[j]=b[j];
    28             b[j]=0;
    29         }
    30     }
    31 }
    32 int main()
    33 {
    34     init();
    35     while(scanf("%d",&n)!=EOF)
    36     {
    37         printf("%lld
    ",a[n]);
    38     }
    39     return 0;
    40 }
    View Code

     

    c.hdu 1398

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

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

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

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

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #define ll long long int
     6 #define MAX 17
     7 #define N 305
     8 using namespace std;
     9 ll a[N];
    10 ll b[N];
    11 void init()
    12 {
    13     int i,j,k;
    14     a[0]=1;
    15     for (i=1; i<=MAX; i++)
    16     {
    17         for (j=0; j<N; j+=i*i)
    18         {
    19             for (k=0; k+j<N; k++)
    20             {
    21                 b[j+k]+=a[k];
    22             }
    23         }
    24         for (j=0; j<N; j++)
    25         {
    26             a[j]=b[j];
    27             b[j]=0;
    28         }
    29     }
    30 }
    31 int main()
    32 {
    33     int n;
    34     init();
    35     while(scanf("%d",&n)!=EOF)
    36     {
    37         if(n==0)
    38         {
    39             break;
    40         }
    41         printf("%lld
    ",a[n]);
    42     }
    43     return 0;
    44 }
    View Code
  • 相关阅读:
    EF获取DbContext中已注册的所有实体类型
    使用一阶微分对图像锐化
    数字图像处理之直方图均衡
    【HDFS】相关概念及常用命令
    【Java】ConcurrentHashMap源码解析
    【Java】对foreach循环的思考
    php生成二维码
    spilt
    strtolower
    in_array
  • 原文地址:https://www.cnblogs.com/wkfvawl/p/9741001.html
Copyright © 2011-2022 走看看