我最近想到了以下问题,我很惊讶似乎没有人提出这个问题:
我知道公式,其中是字符串的长度,是每个字符的计数(考虑大小为的字母表)。因此,字符串toffee
会有个不同的排列。
但是当非常大时(例如),这不再有效,因为计算将超出 long long int的范围,使用BigIntegers会太慢。有没有办法在或时间计算这个?
如果我将中的阶乘预处理到,并且我的“字符串”以长度的数组形式出现,其中每个元素包含每个字母的数量,是否可以在或时间计算它?
感谢您对此有任何帮助:)
答案 0 :(得分:6)
诀窍是要注意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!
和每个的阶乘计数。
这比取消分数中的因子更容易实现。
答案 1 :(得分:2)
字符串的不同排列数总是整数,尽管是除法的结果。那是因为分母的因素基本上“淘汰”了分子的一些因素。所以你可以将除法作为后因子运算来消除,而是将你已经与分母因子相匹配的因子分解出来。
一旦你删除了除法,你只需要进行模乘,这很简单。
答案 2 :(得分:0)
如果N
不是巨大的(也就是说,它足够小,可以使用像Eratosthenes的Sieve那样筛选它),你可以用N!
来计算text=[text stringByAppendingString:@" "];
的素数因子分解。筛子的修改版本。
然后你可以使用素数因子分解来计算除法,取消除法两边存在的因子。
虽然这并没有考虑到你希望结果模数为素数(存在更好的解决方案)这一事实,但在一般情况下可能有用。
答案 3 :(得分:0)
是..存在解决方案。您可以阅读有关模数乘法逆算法的信息。 This
由于答案是使用模数1000000007(也是素数),您可以尝试使用Fermat's little theorem来解决此问题。如果模数为 mod 复杂度为O(N + K * log(mod))。