Atcoder abc300
https://atcoder.jp/contests/abc300/tasks
G P-smooth number
<= n 的,且所有质因子 <= p的数的个数
n 1e16
p 100
4s
1024mb
我的思路
dfs(上限, 质数列表idx) = sum dfs(上限/ 质数[idx]^pwr, idx-1)
然后对于底部做cache
然而并不理想,有cache和没cache 1e15都需要 8~12s,
跟别说1e18
另一个角度是,既然题目都告诉了最大的范围的答案大约是2e10, 所以它大也不算大,
所以考虑meet-in-middle
似乎就过了
代码
https://atcoder.jp/contests/abc300/submissions/me
1 |
|
Ex - Fibonacci: Revisited
$a_n = \begin{cases} 1 & (0 \leq n \lt K) \\ \displaystyle{\sum_{i=1}^K} a_{n-i} & (K \leq n). \\ \end{cases}$
给定$N$, 求 $\displaystyle \sum_{m, m \mathrm{ AND } N = m} a_m$
$K \in [1,5\cdot 10^4]$
$N\in [0,10^{18}]$
6s
1024mb
我的思路
完全没思路啊
只能说m 是N二进制表示的子集
如果 k = 2, 那就是经典的fib, 矩阵快速幂 能算一个,但是不能 同时类和
而这里注意到 m 有 N最高位 和 m 没有N最高位的一一对应
f(v) = (v,v-1,v-2,…,v-k+1) 的行向量
b 是长度k的列向量=(1,0,…,0)^T
$a_v = f(v) \cdot b$
$t_i=2^i$, 如果$v$的$i$位为$0$, 那么
$A$是转移矩阵
$a_{v | t_i} = f(v | t_i) \cdot b = (f(v) \cdot A^{2^i}) \cdot b$
因此,$I$为单位矩阵
$\displaystyle \sum_{m,m\mathrm{AND} N}a_m = f(0) \prod_{i, N \mathrm{AND} 2^i = 2^i} (I+A^{2^i}) \cdot b$
$f(0)=b^T$
问题变成如何计算 转移矩阵的 $2^i$ 幂次
似乎缺少线性代数的知识
因为这里K的确有点大 5e4了都, 别说做乘法,光是表示就很大,虽然本身是稀疏的,但是幂次以后应该就不是稀疏的了
题解
Digit DP with carries
有 $a_1,a_2,…,a_k$面额的硬币, 多少中方案组成N元(mod 998244353)
$k \le 100, S=\sum_{i} a_i \le 1000,N\le 10^{18}$
可以变成digit dp, 大概橙色难度
对于硬币a: newdp[x] = dp[x]+dp[x-a]+dp[x-2a]+dp[x-3a]+...
但对于使用次数
可以拆分成 2的幂次, 于是变成 for i=0..infty, for a, newdp[x] = dp[x]+dp[x-a*2^i]
, 注意这样拆分后外层是循环幂次,而内层是循环a数组
而在执行到i时,注意到对于给定的N mod 2^i
不再会变
而如果 dp[N]
的贡献来源有dp[v]
,那么dp[S = v + 2^i(1?+2?+4?+8?+...)(a_1?+a_2?+...+a_k)]
及v mod 2^i == N mod 2^i
所以其它v mod 2^i != N
的直接忽略掉
所以规模也可以下降了
1 | // carry[i] = carry[i*2^t + (原始N)%(2^t)] |
解释digit DP
显然可以用生成函数表示上面的问题, $a_i$的选择方案就是
$\displaystyle 1+x^{a_i}+x^{2a_i}+x^{3a_i}+\cdots = \frac{1}{1-x^{a_i}}$
答案显然就是 $\displaystyle [x^{N}] \prod_{i\in[1,k]} \frac{1}{1-x^{a_i}}$
又$\displaystyle \frac{1}{1-x}=\frac{1+x}{1-x^2}=\frac{(1+x)(1+x^2)}{1-x^4}=\frac{(1+x)(1+x^2)(1+x^4)}{1-x^8}=\prod_{i\ge 0}(1+x^{2^i})$, 神奇的变换
$\displaystyle F(x)=\prod_{i\in[1,K]}(1+x^{a_1})$, 这里其实就对应于上面的每一轮处理了,
那么答案$\displaystyle [x^N] \prod_{i\ge 0} F(x^{2^{i}})$
引理 B,Q,S_i
B能展开成 $B(x) = \prod_{k \geq 0} Q_{k}(x^{2^k})$
S_i=0/1 为取奇偶列$\mathcal{S}i \left(\sum{n \geq 0} a_n x^n \right) = \sum_{m \geq 0} a_{2m + i} x^m$
令$B_n(x) = \prod_{k \geq 0} Q_{n + k}(x^{2^k})$ 这对应的就是每轮的剩余部分 去除以2的动作
有$\lbrack x^N \rbrack A(x) B_n(x)$
$= \lbrack x^{\lfloor N/2 \rfloor} \rbrack \mathcal{S}_{N \bmod 2}(A(x) B_n(x))$
$=\lbrack x^{\lfloor N/2 \rfloor} \rbrack \mathcal{S}{N \bmod 2} (A(x) Q_n(x)) \prod{k \geq 1} Q_{n+k}(x^{2^{k-1}})$
$= \lbrack x^{\lfloor N/2 \rfloor} \rbrack \mathcal{S}{N \bmod 2}(A(x) Q_n(x)) B{n+1}(x).$
回到digit DP 也就是令$Q_n=F(x)$, 更精简的伪代码
1 | A = 1 // 生成函数 |
Bostan-Mori algorithm and Application to linear recurrence relation
解决问题 $[x^{n}]\frac{P(x)}{Q(x)}$,其中 $P(x),Q(x)$的幂次比较小,而$n$十分大的情况
对于, linear recurrence relation. 同样适用
因为上面的转换相当于 $\displaystyle a_n = \sum_{i=1}^d c_ia_{n-i}, n\ge d$
所以对于$n \ge d$有 $\displaystyle [x^n](1-\sum_{i=1}^d c_ix^i)A(x) = 0$
令$Q(x)= 1-\sum_{i=1}^d c_ix^i$,注意到$A(x)Q(x)$的最大非零幂次$\le d-1$
$P(x) = A(x)Q(x) = (A(x) \mod x^d)Q(x) \mod x^d$
$A(x) = \frac{(A(x) \mod x^d)Q(x) \mod x^d}{Q(x)}$
Botsan-Mori algorithm
把$a_0,a_1,…$ 按照奇偶划分开
偶$a_0,a_2,a_4,\cdots$
奇$a_1,a_3,a_5,\cdots$
首先显然有 $\lbrack x^N \rbrack A(x) = \lbrack x^{\lfloor N/2 \rfloor} \rbrack \mathcal{S}_{N \bmod 2} (A(x))$
$\displaystyle \mathcal{S}_i\left(\frac{P(x)}{Q(x)}\right)$
$\displaystyle =\mathcal{S}_i\left(\frac{P(x)Q(-x)}{Q(x)Q(-x)}\right)$
注意到$Q(x)Q(-x)$ 如果是偶项和奇项相乘的 一正一负抵消,所以结果只有偶次项, 所以分母不改变奇偶
$\displaystyle =\frac{\mathcal{S}_i (P(x)Q(-x))}{\mathcal{S}_0 (Q(x)Q(-x))}$
$\displaystyle =\frac{\mathcal{S}_i (P(x)Q(-x))}{Q(x^{\frac{1}{2}})Q(-x^{\frac{1}{2}})}$
分子 就是 d log d 的卷积
1 | input : P(x), Q(x), N` |
另一方面
$\displaystyle \frac{P(x)}{Q(x)}$
$\displaystyle = \frac{P(x)Q_0(-x)}{Q_0(x)Q_0(-x)}$
$\displaystyle = P(x)Q_0(-x) \times \frac{1}{Q_1(x^2)}$
$\displaystyle = P(x)Q_0(-x) \times \frac{Q_1(-x^2)}{Q_1(x^2)Q_1(-x^2)}$
$\displaystyle = P(x)Q_0(-x) \times Q_1(-x^2) \times \frac{1}{Q_2(x^4)}$
$\displaystyle = P(x) Q_0(-x) \times \prod_{n \geq 1} Q_n(-x^{2^n})$
至此 题目中 如果是求单点, 都可以 $O(K\log K \log N)$算出来
回到题目
上面的 Botsan-Mori 中
在循环里, $A(x) = S_{N\mod 2}(A(x))$
而这里要 $m \mathrm{AND} N = m$
所以也就是改成
$A(x) = S_0(A(x))+S_1(A(x)), N\mod 2=1$
$A(x) = S_0(A(x)), N\mod 2=0$
即可
代码
https://atcoder.jp/contests/abc300/submissions/42091386
1 |
|
总结
G
卡了一下,还是自己想出来, 不过atcoder的机子真的快,我这边2s+,atcoder的只有955ms,不过也可能是我有几个编译参数的原因
???什么 有人用和我想的一样的 记忆化 下降 卡过了??? 而且似乎它记忆的内容更多
Ex
题解各种 书写错误 看自闭了
第一次见这个 Digit DP with carries, 常系数齐次线性递推
线性递推 = 生成方程 的卷积 感觉现在看很显然,自己却没想到
bostan-mori 也是第一次见
似乎这个用线性代数也有办法优化,但是线性代数忘完了
参考
Ryuhei Mori’s article (Japanese)