MegaFactorial

作者:谢兴宇

关键词:矩阵乘法 多项式 倍增 伯努利数 数论

题目简述

我们作出如下递归定义:

给出N,K,B,求f(N,K)在B进制下末尾0的个数,答案对取模。

初步分析

求B进制末尾的0的数量就是求最大的c,使得

如果B是质数的话(2,3,5,7),答案就是将f(n,k)质因式分解后B的指数,我们不妨假定我们已经可以处理这种情况了。

如果B不是质数,因为,所以只有两种情况:

一种是,即b为两个不同的质数的乘积,这样的话显然(如果不显然的话,可以通过算法二中的分析知道)答案是f(n,k)中较大的质数的指数,又可以归约为b是质数的情况;

或者,这时答案就是f(n,k)中p的指数除以x下取整。考虑模意义下的下取整就比较麻烦了。

对于这个可以有两种处理方式:设f(n,k)中p的指数为c,,那么,所以对于模m和模x的情况计算两遍即可;或者我们也可以直接计算,这是因为:

,

因为x最多只有3,所有刚好不会爆long long。。

那么我们现在的问题就是求f(n,k)中p的指数,m中可能有一个因子是2或有一个因子是3。

我们不妨直接改写f,令f(n,k)为原来的f(n,k)中p的指数。那么递归式就可以改写为:

g(n)为n中p的指数。

注意到递归式的第一行,我们可以这样展开:;也可以这样:。即可以转化成某一维是前缀和的形式。那么根据展开的维的不同,就可以有不同的做法。

算法一

考虑,如果我们把看成常数项,那么就意味着都是的线性表示,而n又这么大,所以我们不妨尝试用矩阵乘来解决这个问题。

设由转移到的矩阵是,那么就是先算出,然后再给所有线性表示中的常数项+1。

最终的答案矩阵就是将n p进制分解后把矩阵从大到小依次乘起来即可。

时间复杂度

算法二

由伯努利数的相关知识可以知道,一个关于n的k次多项式的1~n的前缀和是关于n的k+1次多项式。所以看到,我们不妨尝试用多项式做这个题。

我们再仔细看这个递推式,考虑的贡献的话(即令),这实际上就是一个杨辉三角,或者说等于从出发,只能向上或向右走,到达的路径数。所以的贡献是,即i会对贡献

所以。(通过这个式子就可以看出为什么当p增大,不会更大)

,也就是说这可以看做是一个k-1次多项式。这里我们先忽略分母中的,因为这涉及到逆元的问题,我们先认为分母等于1...

那么我们可以倍增来处理这个式子。我们起初只有,最终要求。如果我们有m,那么

这样的话时间复杂度是

但是其实我们没有必要这样做,我们回到这个式子,使用类似算法一的思路,会有

这样时间复杂度就是

最后我们再来处理逆元的问题,实际上有这样的式子:

所以我们可以把中的x都乘到模数里,需要的时候再除下来。中的x并不会很大,当x=2时只有,当x=3时只有

注意这里如果使用只求一遍(模)然后直接下取整的做法的话,因为模数又要乘,计算过程中可能会爆long long,就需要用到的快速乘。

算法三

我们再回到这个式子。。。

注意到我们带进多项式中的是一个等差数列(),或者更进一步,是首项为0的等差数列()。那么我们不妨把公差提出来:是多项式的第项)。那么后面就是一个伯努利数!伯努利数不妨用经典的递推求出。

时间复杂度

不过伯努利数在递推的过程中要除一个,导致模数上要乘的东西更大了。。不过还好,中的2也只有26个,3只有12个。还是可以接受的。

results matching ""

    No results matching ""