模拟61 题解
A. 砖块
简单模拟。
B. 数字
容易发现末尾的0一定是被质因子2和5凑出。
并且,对于任意的$n!$,质因子2的个数不小于质因子5的个数。
简单的暴力$O(n)$做法是将$n!$中的质因子5全部除掉,将2除掉对应的个数就可以了。
注意到$10^k$可以拆为$2^k*5^k$的形式,直接求出结果是困难的。
不妨分别求出答案%$5^k$和%$2^k$的结果,使用$crt$合并得到答案。
容易发现答案%$2^k$的结果一般为0,因为$n!$中质因子2的个数远大于质因子5的个数。
所以只要求出%$5^k$的结果。
先考虑$n!$除掉质因子5之后%$5^k$的结果。
容易发现$n!$中的5可以不断被提出,转化为新的阶乘,子问题递归。
而除去5的倍数的内容可以被分组用快速幂简单算出,这个思想在扩展$lucas$求大组合数中曾多次用过。
很好的一点是,$2^x$在模$5^k$的意义下存在逆元。考试时推到了这里,但是没有想到存在逆元,于是死掉了。
可以求出$n!$中质因子5的个数$x$,将最终答案除掉$2^x$就可以了。
C. 甜圈
考试时打了吉司机线段树,也就是一个带剪枝的暴力搜索。
对于每一个区间,如果整个区间已经非法,那么直接return。
如果整个区间的值是相同的,那么共同赋值。
然而这样做似乎复杂度是有问题的。
最终得了70分,而且比暴力跑的慢。
发现一个简单的hack数据是合法和非法区间一个个交替,每次修改操作会使合法的继续合法,非法的继续非法。
解决办法是,如果线段树的左右区间一个有相同值,一个非法,那么视作该区间有相同值。
这样做复杂度似乎就正确了,然而不会分析。
正解的方法很巧妙:
将每个点都视为一个字符串,不妨对每个字符串哈希。
如果最终哈希值等于要求的哈希值,那么合法。
区间修改哈希值,直接用线段树维护乘法加法标记就可以了。