核心概述:多重组合系数用于计算把总量按多类划分的方式数,值为 (∑k_i)!/(k_1!k_2!…k_n!),提供线性于总和的构造式计算。
原文引述:
Description: Computes . Status: Tested on kattis:lexicography 函数签名:ll multinomial(vi& v)
展开阐述:
- 定义与适用场景
- 定义:给定非负整数序列 k_1,…,k_n,计算多重组合系数 ,对应从 个元素中分配到 n 类、每类大小固定为 k_i 的计数。
- 场景:组合计数、字典序/排列相关问题中的等价类计数与权重评估;原文件标注已在“kattis:lexicography”测试。
- 接口与数据结构
- 输入:向量 v 表示各组计数 k_i。
- 返回:长整型结果 c 为对应的多重组合系数。
- 核心算法流程(依据实现思路)
- 初始化:c = 1;m = v.empty() ? 1 : v[0]。
- 外层按 i 遍历 v 的各项 v[i];内层 j 从 0 到 v[i]-1:
- 令 m 递增:m ← m + 1;
- 累乘并约分:c = c * m / (j + 1);
- 该过程等价于不断将分子中的 (∑k_i)! 展开为连续乘积,并在每段内层循环用 1..v[i] 的因子进行除法,逐步实现对各 k_i! 的约分。
- 复杂度、边界与实现细节
- 复杂度:总迭代次数为 ∑k_i,时间近似 O(∑k_i);常数小、实现简洁。
- 数值边界:结果可能较大,应与题目范围匹配;如需取模需改为模域下的乘法与逆元除法(本节点不引入外部实现)。
- 初值讨论:当 v 为空时按实现取 m=1,通常实际调用会提供至少一项;若存在 k_i=0,对应内层循环不执行,自动跳过该类。
- 顺序影响:算法对 v 的遍历顺序不影响最终结果(因其仅进行分子连续乘积与对各类独立分母的约分),但在整数除法实现时务必保证“整除”发生在每步,避免中间数溢出与精度问题。
- 变体与扩展
- 若需要在模数域计算,可将每次“/ (j+1)”改为乘以模逆;当模非质数时需采用适当的逆元或分解策略(不在本节点展开)。
- 与排列计数的关系:当仅两类时退化为二项式系数;可与 001-组合数学-整数排列 的排列编码思想结合,用以估计重复元素排列数。
- 正确性直观
- 分子 (∑k_i)! 是所有元素的全排列数;除以每类内部的 k_i! 去除不可区分的排列,得到将元素分到各类且类内无序的方案数。实现通过逐段累积分子并与 1..k_i 逐步相抵来完成这一定义式。