数论_母函数_指数型母函数

母函数

简单介绍

定义:
对于序列a0,a1,a2,a3…an构造一个函数:
G(x)=a0+a1x+a2x2+a3x3+…
称函数G(x)是序列a0,a1,a2,a3…an的母函数。
举例:
以选砝码为例,母函数就是利用次幂来表示面值和数量,例如:(1+x)用来表示1个1克的砝码,(1+x2)用来表示1个2克的砝码,(1+x3)用来表示1个3克的砝码,(1+x4)用来表示1个4克的砝码。
表示这几个砝码的组合情况时,只要将各个式子乘起来就OK了。例子中的四个式子相乘我们可以得到1+x+x2+2x3+2x4+2x5+2x6+2x7+x8+x9+x10,每个项的系数就表示每一种的组合情况,比如3,可以选1和2,也可以选一个3;而对于2,只能选一个2。
关键点:
实现对多项式的展开。

代码模板

这里需要说一下拆分数的概念:整数拆分成若干整数的和不同的拆分法的总数叫做拆分数,该代码就是求整数n的拆分数的。

#include<iostream>
#include <bits/stdc++.h>//母函数一般用来解决整数拆分、邮票组合、砝码称重一类的问题
#define lmax 1000//该例子是以整数拆分为例的母函数代码,即读入一个n,求这个数的拆分数

using namespace std;

int c1[lmax],c2[lmax];
int elem[lmax];//当给定的数值没有规律时,可以直接用数组存储,用下标取数
int main()//普通型母函数模板
{
    int n,i,j,k;
    while(cin>>n)
    {
        for(i=0;i<=n;i++)
        {
            c1[i]=0;
            c2[i]=0;
        }
        for(i=0;i<=n;i++)
        {
            c1[i]=1;
        }
        for(i=2;i<=n;i++)//关键的三层for循环,总共有n个括号,做n-1趟for循环
        {
            for(j=0;j<=n;j++)//c1数组表示当前括号,c2数组表示当前的下一个括号,两层for循环遍历一遍
                for(k=0;k+j<=n;k+=i)
                {
                    c2[j+k]+=c1[j];
                }
            for(j=0;j<=n;j++)//将循环得到的值赋给c1数组
            {
                c1[j]=c2[j];
                c2[j]=0;
            }
        }
        cout<<c1[n]<<endl;
    }
    return 0;
}

指数型母函数

母函数解决的是组合型问题,而指数型母函数解决的则是排列型问题。

代码模板

#include<iostream>
#include <bits/stdc++.h>//指数型母函数一般用来解决组合一类的问题

using namespace std;
const int lmax=21;//因为涉及到阶乘,因此数据量一般不会很大
double c1[lmax],c2[lmax];
int val[lmax],F[lmax];
void factorial()//将阶乘的结果存到F数组中
{
    F[0]=1;
    for(int i=1;i<=20;i++)
    {
        F[i]=F[i-1]*i;
    }
}

int main()//指数型母函数模板
{
    int n,m,i,j,k;
    factorial();
    while(~scanf("%d%d",&n,&m))
    {
        for(i=0;i<n;i++)
        {
            scanf("%d",&val[i]);
        }
        for(i=0;i<=n;i++)
        {
            c1[i]=0;
            c2[i]=0;
        }
        //memset(c1,0,sizeof(c1));//这里的初始化可以用memset来写
        //memset(c2,0,sizeof(c2));
        for(i=0;i<=val[0];i++)
        {
            c1[i]=1.0/F[i];
        }
        for(i=2;i<=n;i++)//关键的三层for循环,总共有n个括号,做n-1趟for循环
        {
            for(j=0;j<=m;j++)//c1数组表示当前括号,c2数组表示当前的下一个括号,两层for循环遍历一遍
                for(k=0;k+j<=m&&k<=val[i];++k)
                {
                    c2[j+k]+=c1[j]/F[k];
                }
            for(j=0;j<=m;j++)//将循环得到的值赋给c1数组
            {
                c1[j]=c2[j];
                c2[j]=0;
            }
        }
        printf("%.0f\n",c1[m]*F[m]);
    }
    return 0;
}

母函数这一边很多东西都需要很多实践才能理解地更加透彻,我也是在不断的摸索中写出的着一些东西,还有很多不足。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值