「HDU1521」排列组合

「HDU1521」排列组合

problem

Solution

生成函数入门题

\(i\)种物品有\(n_i\)个,构造指数型生成函数

\[G_e(x)=\sum_{k=1}^{min(n_i,m)}\frac{x^k}{k!} \]

把所有物品的生成函数乘起来

设最后得到的多项式的\(m\)次项为\(a_m\)

那么答案即为

\[a_m*m! \]

Code

很丑,很不优雅,慎看

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;

template <typename T>void read(T &t)
{
	t=0;int f=0;char c=getchar();
	while(!isdigit(c)){f|=c=='-';c=getchar();}
	while(isdigit(c)){t=t*10+c-'0';c=getchar();}
	if(f)t=-t;
}

const int maxn=10+5,maxm=maxn;
ll n,m;
double fac[maxm];

double a[maxm],b[maxm],c[maxm];

void Pre()
{
	fac[0]=1;
	for(register int i=1;i<=10;++i)
		fac[i]=fac[i-1]*i;
}

ll gcd(ll a,ll b)
{
	return b?gcd(b,a%b):a;
}

int main()
{
	Pre();
	while(scanf("%lld%lld",&n,&m)!=EOF)
	{
		memset(a,0,sizeof(a));
		ll k;
		read(k);
		for(register int i=0;i<=min(k,m);++i)a[i]=1.0/fac[i];
		--n;
		while(n--)
		{
			read(k);
			memset(b,0,sizeof(b));
			for(register int i=0;i<=min(k,m);++i)b[i]=1.0/fac[i];
			memset(c,0,sizeof(c));
			for(register int i=0;i<=m;++i)
				for(register int j=0;i+j<=m;++j)
					c[i+j]+=a[i]*b[j];
			memcpy(a,c,sizeof(c));
		}
		printf("%.0f\n",fac[m]*a[m]);
	}
	return 0;
}
posted @ 2019-04-01 10:28  lizbaka  阅读(325)  评论(0编辑  收藏  举报