「HDU1521」排列组合
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
",fac[m]*a[m]);
}
return 0;
}