「HDU1521」排列组合

problem

Solution

生成函数入门题

ii种物品有nin_i个,构造指数型生成函数

Ge(x)=k=1min(ni,m)xkk!G_e(x)=\sum_{k=1}^{min(n_i,m)}\frac{x^k}{k!}

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

设最后得到的多项式的mm次项为ama_m

那么答案即为

amm!a_m*m!

Code

很丑,很不优雅,慎看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#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;
}