• 母函数模板解释


    感谢:母函数模板解释

    母函数模板解释

    母函数模板 
    1;母函数应用于——————形式上说,普通型生成函数用于解决多重集的组合问题,而指数型母函数用于解决多重集的排列问题.。现在我们先讨论普通生成函数;

    2;定义; 
    (1+x)^n = 1 + C(n,1)x +C(n,2)x^2 + C(n,3)x^3+~~~~~~~~~+C(n,n)^n; 
    ==> G(x)=a0 + a1x + a2x^2 + ~~~~~ + anx^n;

    函数G(X)就称序列a0,a1,a2,a3~~~~~an的母函数; 
    看一个经典的例子;

    例一; 
    有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∧2为例; 
    2克的砝码有两种状态,取or不取; 1*x^0+1*x^2;就是1+1*x^2; 
    看联系;G(x) = (1+x^1)(1+x^2)(1+x^3)*(1+x^4);每个括号内都表示每种砝码的情况。 
    =1+x+x^2+2*x^3+2*x^4+2*x^5+2*x^6+2*x^7+x^8+x^9+x^10;

    从最后面的式子可以知道;可以称出1g到10g,前面的系数就是方案数。指数表示可以称出的重量。 
    列如5g就找到x系数为5的式子;2*x^5系数为2则有2种方案可以称出5g;

    例二; 
    用1分,2分,3分的邮票可以贴出数值的方案数。 
    该例子对比例一的区别,这里是无限的每种邮票都可以;1~无限。 
    =======G(x)=(1+x+x^2+x^3+……)(1+x^2+x^4+x^6……)(1+x^3+x^6+x^9……)+( ……); 
    然后就是同样的, 
    拆开后;前面的系数就是方案数。指数表示可以称出的重量。

    对于这种母函数的应用应该懂了吧。 
    个人理解;就是一句话,把每种列子的每种情况列出相乘就是要求的母函数了,母函数拆开之后就是结果了,幂表示情况,前面的系数表示该种情况下的方案种类;

    现在我们考虑的是怎么用代码实现例二的情况呢。就是说我要怎么用用代码实现,输入一个数可以输出这种重量的方案数。 
    一位大牛说,我们怎么笔算的就用这种思维去实现,然而……还是不会。

    先说一下核心思路吧。 
    **1;要开两个数组,c1,c2; 
    C1;保存当前得到的多项式各式系数; 
    C2;保存每次计算是的临时结果; 
    并且在之后每计算一次完毕之后就要把c2赋值给c1,并且将c2初始化为0; 
    2;三重循环 
    第一重;记录它正在与第几个多项式相乘。 
    第二重;表示c1中每一项; 
    第三重;被后面相乘的每一项**。

    在根据这些去落实代码吧;

    while(scanf("%d",&n) != EOF){
            for(i = 0; i <= n; i++){//初始化;要注意并不是每次都是这样初始化的。
                c1[i] = 1;
                c2[i] = 0;
            }
            for(i = 2; i <= n; i++){
                for(j = 0; j <= n; j++){
                    for(k = 0; k+j <= n; k += i){ //这里的k+=i表示的是表达式i中幂的变化规律。刚好是加i;注意适当变化。
                        c2[k+j] += c1[j];
                    }
                }
                for(j = 0; j <= n; j++){
                    c1[j] = c2[j];
                    c2[j] = 0;
                }
            }
            printf("%d
    ",c1[n]);
        }
    ;

    分析代码; 
    1;

     for(i = 0; i <= n; i++){

    //初始化;要注意并不是每次都是这样初始化的。

    c1[i] = 1; c2[i] = 0; } 

    初始化;这样初始化的条件是每项都有从1到n克都存在的情况下,不能存在中间有一项没有这种情况。 
    列如例子2082就是不能这样的,他中间存在没有的情况。

    2;三重循环;

    for(i = 2; i <= n; i++){//表示第i个表达式;
                for(j = 0; j <= n; j++){//表示、c1中的每一项。结果是幂;
                    for(k = 0; k+j <= n; k += i){ //表示与第i个表达式中的幂为k的项相乘;
                        c2[k+j] += c1[j];//这里是累加。

    看另外一种模板;代码出自于杭电2082;

    memset(c1, 0, sizeof(c1));
    memset(c2, 0, sizeof(c2));
    c1[0]=1;//有些是0,则不能套用模板中的都等于1;
            //c1[0]=1;相当于入口、 
            for(i = 1; i <= 26; i++){ 
                for(j = 0; j <= 50; j++){//c1的各项的指数
                    for(k = 0; k <= x[i] && j+k*i <= 50; k++){ 
                        c2[j+k*i] += c1[j];
                    }//这里的k表示表达式中的第k项,并且该项的幂是k*i;  
                }
                for(j = 0; j <= 50; j++){
                    c1[j] = c2[j];
                    c2[j] = 0;
                }
            }

    对比一下上个代码; 
    区别; 
    1;初始化那里不同,这里只是c1[0]=1;而不是全部初始化为1;因此这样的初始化适用范围更广,可以是连续的情况。 
    2;第三重循环那里不同,不再是k+=I;而是k++了。然而这里的区别很大,。 
    这里的k表示的是第i个表达式中的第k项,并且该项的幂是k*i**; 
    前面那个代码k表示的是与第i个表达式中的幂为k的项相乘。 
    一个表示k项一个表示幂为k,这里注意区分

  • 相关阅读:
    bx值
    玲珑杯1147
    Castle
    美团 CodeM 复赛」城市网络
    上海五校赛 密码破解
    上海五校赛 零件组装
    opencv色彩空间
    opencv对图片每个像素操作
    opencv图像的读取和保存以及调用摄像头。
    numpy的logspace产生等比数列
  • 原文地址:https://www.cnblogs.com/kimsimple/p/6714516.html
Copyright © 2020-2023  润新知