「HDU1521」排列组合
problem
Solution
生成函数入门题
第i种物品有ni个,构造指数型生成函数
Ge(x)=k=1∑min(ni,m)k!xk
把所有物品的生成函数乘起来
设最后得到的多项式的m次项为am
那么答案即为
am∗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; }
|