母函数

本文详细介绍了母函数的概念及其在解决整数划分问题中的应用,包括普通型母函数、指数型母函数等,并通过三个具体题目(hdu1208、hdu1085、hdu1521)的解析,展示了不同场景下母函数的实现方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

hdu 1208
题意:给定n求将n进行整数划分的种类数。
思路:母函数。
什么是母函数呢?前面那个链接已经讲的很清楚了,不过有点理论化,可以看看这篇博客比较接地气。
我个人的理解就是将每一个东西能提供的价值看作是一个一元多项式的系数,然后将所有东西的一元多项式乘起来,然后系数就代表的就是组成系数的方案数有多少种。
普通型母函数

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=1e6+10;
LL c1[maxn],c2[maxn];//c1 前一项的系数   c2计算过程当中上的系数
LL solve(int n)
{
    for(int i=0;i<=n;i++)//初始化c1为第一项的系数
    {
        c1[i]=1;//指数为i的系数
        c2[i]=0;
    }
    for(int i=2;i<=n;i++)//一共有多少项
    {
        for(int j=0;j<=n;j++)//第i-1项各个元素的指数
        {
            for(int k=0;k+j<=n;k+=i)//第i项各个元素的指数
            {
                c2[k+j]+=c1[j];//x^k*x^j=x^(k+j)
            }
        }
        for(int i=0;i<=n;i++)//更新前一项的各个元素系数
        {
            c1[i]=c2[i];
            c2[i]=0;
        }
    }
    return c1[n];//x^n前的系数代表的就是方案数
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        printf("%lld\n",solve(n));
    }
}

hdu 1085

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=1e5+10;
LL c1[maxn],c2[maxn];//c1 前一项的系数   c2计算过程当中上的系数
LL cnt[10];
LL z[3]= {1,2,5};
LL solve()
{
    memset(c1,0,sizeof(c1));
    memset(c2,0,sizeof(c2));
    for(int i=0; i<=cnt[0]; i++) //初始化c1为第一项的系数,这里有上限
        c1[i]=1;
    LL Max=0;
    for(int i=0; i<3; i++)//计算最大指数
        Max+=cnt[i]*z[i];
    for(int i=1; i<=2; i++)
    {
        for(int j=0; j<=Max; j++)
        {
            if(c1[j]!=0)
            for(int k=0; k/z[i]<=cnt[i]&&j+k<=Max; k+=z[i])//注意上限
            {
                c2[k+j]+=c1[j];
            }
        }
        memcpy(c1, c2, sizeof(c1));
        memset(c2, 0, sizeof(c2));
    }
    for(int i=0;; i++)//找到的第一个系数为0的
        if(!c1[i])
            return i;
}
int main()
{
    while(~scanf("%lld%lld%lld",&cnt[0],&cnt[1],&cnt[2])&&(cnt[0]||cnt[1]||cnt[2]))
    {
        printf("%lld\n",solve());
    }
}

指数型母函数
大佬博客
hdu 1521

#include<cstdio>//和普通母函数一样只不过多了一个去重集的过程即    /(除) 阶乘
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=1e5+10;
int num[maxn];
double c1[maxn],c2[maxn],fac[maxn];
void init()
{
    fac[0]=fac[1]=1;
    for(int i=2; i<=10; i++)
        fac[i]=fac[i-1]*i;
}
void solve(int n,int m)
{
    for(int i=0; i<=10; i++)
        c1[i]=c2[i]=0.0;
    for(int i=0; i<=num[0]; i++)
        c1[i]=1.0/fac[i];
    for(int i=1; i<n; i++)
    {
        for(int j=0; j<=m; j++)
        {
            for(int k=0; k+j<=m&&k<=num[i]; k++)
            {
                c2[k+j]+=c1[j]/fac[k];
            }
        }
        memcpy(c1,c2,8*m+8);
        memset(c2,0,8*m+8);
    }
    printf("%.0lf\n",c1[m]*fac[m]);
}
int main()
{
    init();
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=0; i<n; i++)
            scanf("%d",&num[i]);
        solve(n,m);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值