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));
}
}
#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());
}
}
#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);
}
}