• 「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
    ",fac[m]*a[m]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    square(正方形)
    敌兵布阵
    Addition Chains(加法链)
    贪心算法理论
    难题,未解决
    Linux上vi(vim)编辑器使用教程
    linux下md5sum的使用
    Java读取csv文件
    S2JDBCタイプセーフAPI
    S2JDBCチュートリアル
  • 原文地址:https://www.cnblogs.com/lizbaka/p/10634963.html
Copyright © 2020-2023  润新知