zju3183 Counting Binary Trees

题意:求(sigema c[n]) % m, 1 <= n <= 10000, 1 <= m <= 1000000000, c[n]是第n个catalan数
思路:重点是求c[n] % m, 首先catalan数有递推式 c[n] = (4 * n - 2) / (n + 1) * c[n - 1], 如果式子只带乘法的话, 那么只要在计算过程中把%m内嵌就可以了, 当式子带除法时, 这里的做法是把除法变为乘法, 再用上面的方法来解. 我们知道, a / b % m == a * ((b^-1) % m) % m, 其中b^-1是b关于m的逆元, 可用扩展欧几里德求得, 但是前提条件是b与m互质, 而这题的m是任意的, 所以不能直接求逆元, 但可以通过一些处理使得互质条件满足. 具体做法是, 把c[i]表示成两个数的乘积, 然后分别维护, 第一个数与m互质, 第二个数的素因子都是m的素因子, 前面一个数用一个"数"来维护, 后一个数可以用m的素数表来维护, 该表第i项记录的是所维护的数关于m的第i个素数的指数. 计算(n+1)关于m的逆元前, 先对n+1作m的素因子分解, n+1中每带一个m的素因子, 就将c[n-1]的素数表内对应素数的指数减1, 然后因为n+1分解后剩下的部分与m互质, 我们可以只求这部分的逆元(不妨称为x), 于是除法就变成了乘法. 但这样还不够, 我们还要完成c[n]的两个部分的维护才能说我们求出了c[n], 别忘了前面还有个(4 * n - 2). 和上面的方法类似, 我们先求t = (4 * n - 2) * x, 然后对t作m的素因子分解, 与m互质的部分与上述的第一个数累乘并mod m, 而另一部分则累加到素数表中, 这样就完成了c[n]的维护, 可以进行后续的计算. 最后, c[n] % m的结果就是从素数表中取m的素因子, 根据其指数累乘到第一个数中, 过程中mod m.
posted @ 2009-06-08 18:04  Beetlebum  阅读(518)  评论(0编辑  收藏  举报