CodeChef November Challenge2019 Winning Ways (3-FWT)
CodeChef November Challenge2019 Winning Ways (3-FWT)
显然每个把每个数换成其因子个数-1,就能转为一个扩展的$\text{Nim}$游戏
每次操作$1,2,\cdots,k$堆的$\text{Nim}$游戏,其判定方法是:
将每个数二进制分解,对于每个二进制位上分别计算1的个数$\mod (k+1)$,如果均为0则先手必败
对于这道题$k=3$,我们考虑将其转为二进制之后的形式累成3进制,然后就能进行3进制按位不进位加法,即类异或
然后问题实际上有非常多的部分需要考虑
Part1 如何求因子个数
一个简单的方法是枚举$[1,\sqrt n]$判断是否整除,复杂度过高
对于$n=\prod p_i^{c_i}$($p_i$为质数),其因子个数为$\prod (c_i+1)$
由这个式子对于$n$进行质因数分解,枚举$[1,\sqrt n]$中的质数,复杂度为$O(\pi(\sqrt n))=O(\frac{\sqrt n} {\log n})$,这个应该够了?
然后是一个常规套路型的分解方法:
先对于$[1,n^{\frac{1} {3} }]$的质数筛$n$,剩余的部分只有3种情况
1.$n$被筛成1了
2.$n$被筛到只剩一个质数,可以用$\text{Miller_Rabin}$算法快速判断,可以参考
3.$n$仍然是若干质数的乘积,此时质因子必然$>n^{\frac{1} {3} }$,因此最多只有两个
那么只需要判断$n$是否是完全平方数即可
总复杂度为$O(w\cdot \log n+\frac{n^{\frac{1} {3} }} {\log n})$,其中$w$为$\text{Miller_Rabin}$筛选次数
1 | const int N=2e5+10; |
Part2 快速计算答案
$10^9$以内的数,最大因子个数为$1334$,这个数为$931170240$
转成二进制之后最多包含$11$位,三进制下最大为$3^{11}-1=177146$,令这个上界为$M$
一种非常暴力的方法就是直接枚举,$NM$计算每次选择一个数,复杂度为$O(NMK)$,应该可以通过$N\leq 12$的数据
一个比较浅显的优化可以用快速幂维护乘法,复杂度为$O(M^2\log K)$
由于是3进制类异或,接下来考虑用$\text{3-FWT}$优化乘法,可以参考
模数为$P=10^9+7$,不存在整数$3$阶单位根,因此要用类似拆系数$\text{FFT}$方法做
复杂度为$O(M\log M\log K)$,似乎已经比较小了,但是常数非常大,应该难以通过
1 | int R;// R为上界 |
Further
对于形式幂级数多项式,我们知道$K$次幂的循环卷积可以直接 $\text{DFT}$一次,每一位快速幂,然后$\text{IDFT}$
同理的,如果你学习了$\text{K-FWT}$就知道这就是一个按$K$进制位,每一位分别进行循环卷积,因此也可以用类似的方法做
但是遇到一个非常大的问题就是无法找到模意义下的$3$阶单位根(指$3\not |(P-1)$)
如果用复平面单位根$\omega_n=cos(\frac{2\pi} {n})+sin(\frac{2\pi} {n})\cdot i$($i=\sqrt {-1})$,无法在计算时保证值域精度
这里由于$n=3$比较特殊,发现$\omega_3=cos(\frac{2\pi} {3})+sin(\frac{2\pi} {3})\cdot i=-\frac{1} {2}+\frac{\sqrt 3} {2}\cdot i$
而$3$在$\mod 10^9+7$下存在二次剩余,因此可以用一个模意义下的复数描述复平面单位根
应该是有通行的单位根求法,会根据$n$不同要用更复杂的高维复数描述,但是我并不会.jpg
总复杂度为$O(M(\log M+\log K))$,分别为进行$\text{3-FWT}$以及快速幂的复杂度
Code总览:
1 |
|