algorithm - 字符串模素数的不同排列

标签 algorithm math

我最近想到了以下问题,我很惊讶似乎还没有人问这个问题:

给定一个字符串,它存在多少种不同的排列,取模 1000000007

我知道公式formula其中 N是字符串的长度,A1A2AK是每个字符的计数(考虑大小为 K 的字母表)。因此,字符串 toffee 将具有 180不同的排列。

但是当 N 时,这不再有效了。可以非常大(比如 100000 ),因为计算 Nfactorial会超出 long long int 的范围,并且使用 BigIntegers 会太慢。有没有什么办法可以计算出这个,比如说,NNlogN时间?

如果我预处理来自 1 的阶乘至 N ,我的“字符串”以长度数组的形式出现 K其中每个元素包含每个字母的计数,是否可以在 K 中计算它?或 KlogK时间?

对此有任何帮助将不胜感激:)

最佳答案

技巧是注意 p = 10^9 + 7 是质数。因此,我们可以使用乘法逆元和Fermat's little theorem。将公式中的除法转换为逆的乘法:

n! / (a1!*...*ak!) = 

n! * a1!^(p - 2) * ... * ak!^(p - 2) (mod p)

这将是您的公式 mod p,没有除法且易于实现(只需使用模块化 exponentiation by squaring )。

复杂度将为 O(k log p + n),因为我们有 O(k) 次乘法,对于每个乘法,O(log p) 求幂,我们还必须计算 n! 和每个计数的阶乘。

这比抵消分数中的因子更容易实现。

关于algorithm - 字符串模素数的不同排列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32713762/

相关文章:

math - 如何删除贝塞尔曲线的节点,使曲线的形状不改变?

android - 不存在这样的 acos 函数

math - 盒子到球体碰撞

algorithm - 次阶乘模质数 (!n mod p)

language-agnostic - 如何编写所有可计算函数的枚举?

algorithm - 最小乘积生成树与最小和生成树不同吗?

algorithm - 图的临界点 : reach all nodes in minimum number of points and weight

c - Vigenere Cipher - 无法解释的细微差别

java - 与 "iteration is linear in the sum of the number of entries and the number of buckets"混淆

arrays - 在不同数组中查找 "most common elements"的算法