普通型母函数:
解决不重复的组合问题,整数拆分问题。
基本会构造多项式,然后利用一下多项式的乘法即可。多项式的系数即为方案数。
hdu1085
hdu1398[模板题]
hdu1171
hdu1709
hdu1028
hdu2069
hdu2152
(1) hdu1028[模板]:

#include <bits/stdc++.h>
using  namespace std;
int a[130],b[130];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        for(int i=0;i<=n;i++)
            a[i]=1;
        for(int i=2;i<=n;i++)//共n个多项式
        {
            memset(b,0,sizeof(b));//临时数组存系数,每次两个多项式项乘时,都要清空
            for(int j=0;j<=n;j++)
            {
                for(int k=0;k<=n;k+=i)
                {
                    if(j+k>n)//只要计算幂<=n的项的系数即可
                        break;
                    b[j+k]+=a[j];
                }
            }
            for(int j=0;j<=n;j++)
                a[j]=b[j];
        }
        printf("%d\n",a[n]);
    }
    return 0;
}

(2)hdu2069[对所有硬币的总数进行限制]
网上有很多答案是用dp写的,但用母函数也可以。
因为对硬币总个数有限制,所有不能按照一般的多项式相乘,每次相乘之前,要特判一下这个情况的硬币个数是否超出了限制(我用一个vector数组来保存)。
但一直WA,最后发现原因,当一种情况满足条件时,把它push到vector数组中,但这是这次相乘的结果,不能在这次用,否则会重复。

#include <bits/stdc++.h>
using namespace std;
int cent[7]={0,1,5,10,25,50};
int a[300],b[300];
vector<int>num[300];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        for(int i=0;i<=n;i++)
            num[i].clear();
        for(int i=1;i<=min(n,100);i++)
        {
            a[i]=1;
            num[i].push_back(i);
        }
        a[0]=1;
        for(int i=2;i<=5;i++)
        {
            for(int j=0;j<=n;j++)
            {
                for(int k=1;k*cent[i]<=n;k++)
                {
                    if(j+k*cent[i]>n||k>100)
                        break;
                    if(j==0)
                    {
                        b[k*cent[i]]++;
                        num[k*cent[i]].push_back(k);
                        continue;
                    }
                    for(int w=0;w<num[j].size()&&w<a[j];w++)//wa点 &&w<a[j]
                    {
                        if(num[j][w]+k<=100)
                        {
                            b[j+k*cent[i]]++;
                            num[j+k*cent[i]].push_back(num[j][w]+k);
                        }
                    }
                }
            }
            for(int j=1;j<=n;j++)
            {
                a[j]+=b[j];
                b[j]=0;
            }
        }
        printf("%d\n",a[n]);
    }
    return 0;
}

指数型母函数:
可重集合的排列组合问题:
hdu1521:
[模板]

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=15;
double a[maxn],b[maxn];
int fact[maxn];
int num[maxn];
void init()
{
    fact[0]=1;
    for(int i=1;i<maxn;i++)
        fact[i]=i*fact[i-1];
    memset(a,0,sizeof a);
    memset(b,0,sizeof b);
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        for(int i=1;i<=n;i++)
            scanf("%d",&num[i]);
        for(int i=0;i<=num[1];i++)//第一项初始赋值
            a[i]=1.0/fact[i];
        for(int i=2;i<=n;i++){//循环第2到第n项
            for(int j=0;j<=m;j++)
                for(int k=0;k<=num[i]&&k+j<=m;k++)
                b[k+j]+=a[j]/fact[k];
            for(int j=0;j<=m;j++){
                a[j]=b[j];
                b[j]=0;
            }
        }
        printf("%.0f\n",a[m]*fact[m]);
    }
}