zoukankan      html  css  js  c++  java
  • hdu1521

    博客图片

    题目链接

    hdu1521

    题目概述

            给出(n)中元素和这些元素的数量,计算选择出(m)件物品的可能的排列的数目,其中((1leq n,m leq 10).)

    解题思路

            指数型母函数的概念题,<组合数学>这本书中有一个定理:

    [ S={n_1a_1, n_2a_2,dots,n_ka_k},\, (n_i=1,2,3,dots, i=1,2,3,dots,k)\ The \,exponential \,generating \,function \,g^{(e)}(x)\,of \,the \,sequence \,h_0, h_1, h_2, cdots, h_n, cdots, \,is \,given \,by:\ g^{(e)} =f_{n_1}(x)f_{n_2}(x)cdots f_{n_k}(x)\ f_{n_i} = 1+x+frac{x^2}{2!}+cdots+frac{x^{n_i}}{n_i!} \,(i=1,2,cdots,k) ]

    很明显这个题就是上面定理的概念题,已知(a_i)(n_i),计算(m)排列的个数.

            下面的表格给出了一次计算的过程:
    下面通过这个表格给出计算((1+frac{x^1}{1!}+frac{x^2}{2!})(1+frac{x^1}{1!}+frac{x^2}{2!}+frac{x^3}{3!}))的计算过程:
    (表格A(上一轮计算的结果))

    0 1 2 3 4 5 6 7 8 9
    1 (frac{1}{1!}) (frac{1}{2!})

    (表格B(这一轮计算的结果))

    0 1 2 3 4 5 6 7 8 9
    1 (frac{1}{1!}) (frac{1}{2!}) (frac{1}{3!})
    1 (frac{1}{1!}) (frac{1}{2!}) (frac{1}{3!})
    (frac{1}{2!}) (frac{1}{2!2!}) (frac{1}{2!3!})

    (整理之后是这一轮计算的值(对应程序中的temp))

    0 1 2 3 4 5 6 7 8 9
    1 2 (frac{3}{2}) (frac{7}{6}) (frac{5}{12}) (frac{1}{12})

    (更新这一轮计算的结果准备计算下一轮(对应程序中的buf))

    0 1 2 3 4 5 6 7 8 9
    1 2 (frac{3}{2}) (frac{7}{6}) (frac{5}{12}) (frac{1}{12})

    代码实现

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 15;
    double buf[N];
    double temp[N];
    ll F[N];
    ll nums[N] = {2,3,1};
    
    void calculate(int n = 3){
        fill(buf, buf + N, 0);
        for (int i = 0;i <= nums[0];i++){
            buf[i] = 1.0 / F[i];
        }
        // for (int i = 0; i < N; ++i){
        //     printf("%.1f ", buf[i]);
        // }
        // printf("
    ");
        fill(temp, temp + N, 0);
        ll sum = nums[0];
        for (int k = 1; k < n; ++k){
            for (int i = 0; i <= sum; ++i){
                for(int j = 0; j <= nums[k]; j++){
                    temp[i + j] += buf[i]/F[j];
                }
            }
            // for (int i = 0; i < N; ++i){
            //     printf("%.0f ", temp[i]*F[i]);
            // }
            // printf("
    ");
            memcpy(buf, temp, sizeof(double) * N);
            fill(temp, temp + N, 0);
            sum += nums[k];
        }
    }
    
    int main(int argc, const char** argv) {
        F[0] = 1ll;
        for(int i = 1; i < N; i++){
            F[i] = F[i - 1] * i;
        }
        calculate();
        int n,m;
        while (~scanf("%d%d",&n, &m)){
            for (int i = 0;i < n; ++i){
                scanf("%lld", &nums[i]);
            }
            calculate(n);
            printf("%.0f
    ", buf[m]*F[m]);
        }
        return 0;
    }
    

    这个程序有以下几点要注意的:

    1. 那个sum表示的是已经计算出的最高次项,由当前的元素出现的次数决定;

    2. 第二个是因为最后的buf存储的系数实际是除以阶乘之后的,所以要用double来存储,并且在最后输出结果是要再乘以对应的阶乘.

    3. 就是这里面表示第二个乘式的(x^i)的变化的j每一步的增长是一步,可以从上面的定理中看出.

    其它

  • 相关阅读:
    TdxGaugeControl
    TdxSkinController
    delphi TdxMemData 使用
    深入方法(16)- 方法的顺序
    深入方法(15)- 调用其他单元的函数
    深入方法(14)- 在TForm1 类内声明的方法
    深入方法(13)- 在 interface 区声明的方法
    深入方法(12)- implementation 区中的方法
    深入方法(11)- 参数前缀
    深入方法(10)- 默认参数
  • 原文地址:https://www.cnblogs.com/2018slgys/p/13322007.html
Copyright © 2011-2022 走看看