1 条题解
-
0
好的,我们先来分析一下这道题和给出的代码。
题目理解
我们有一个 的表格,格子 的值是 ,其中 是 Fibonacci 数列()。
要求表格中所有数的乘积,对 取模。
问题转化
设 $P(n, m) = \prod_{i=1}^n \prod_{j=1}^m f[\gcd(i, j)]$。
我们枚举 ,那么 的 对数是多少?
设 ,那么 ,且 。
所以:
$$P(n, m) = \prod_{d=1}^{\min(n, m)} f[d]^{\sum_{x=1}^{n/d} \sum_{y=1}^{m/d} [\gcd(x, y) = 1]} $$
指数上的计数
指数部分:
$$\sum_{x=1}^{n/d} \sum_{y=1}^{m/d} [\gcd(x, y) = 1] $$可以用莫比乌斯反演:
$$\sum_{k=1}^{\min(n/d, m/d)} \mu(k) \cdot \left\lfloor \frac{n}{dk} \right\rfloor \cdot \left\lfloor \frac{m}{dk} \right\rfloor $$于是:
$$P(n, m) = \prod_{d=1}^{\min(n, m)} f[d]^{\sum_{k} \mu(k) \lfloor n/(dk) \rfloor \lfloor m/(dk) \rfloor} $$
进一步化简
令 ,则 ,。
指数部分变成:
$$\sum_{t=1}^{\min(n, m)} \left\lfloor \frac{n}{t} \right\rfloor \left\lfloor \frac{m}{t} \right\rfloor \sum_{d \mid t} \mu\left(\frac{t}{d}\right) \cdot [\text{指数上多了一个} \dots] $$其实更直接地,我们设 ,,那么:
$$P(n, m) = \prod_{g=1}^{\min(n, m)} f[g]^{\sum_{k=1}^{\min(n/g, m/g)} \mu(k) \lfloor n/(gk) \rfloor \lfloor m/(gk) \rfloor} $$换元 :
$$P(n, m) = \prod_{T=1}^{\min(n, m)} \left[ \prod_{g \mid T} f[g]^{\mu(T/g)} \right]^{\lfloor n/T \rfloor \lfloor m/T \rfloor} $$
代码中的实现
代码中定义:
在
init()
函数里:- 先线性筛出 和 (Fibonacci 数列模 )。
- 初始化
s[i] = 1
。 - 对于每个 (即 ),枚举倍数 ,如果 ,则乘 ;如果 ,则乘 的逆元。这实际上是在计算: [ s[j \cdot i] \times= f[i]^{\mu(j)} ] 因为 ,,,所以 。
这样就能在 时间内预处理出 数组。
查询部分
查询时: [ P(n, m) = \prod_{T=1}^{\min(n, m)} s[T]^{\lfloor n/T \rfloor \lfloor m/T \rfloor} ] 利用数论分块,对 和 相同的区间 一起计算: [ \prod_{T=l}^r s[T]^{\lfloor n/T \rfloor \lfloor m/T \rfloor} = \left( \prod_{T=l}^r s[T] \right)^{\lfloor n/l \rfloor \lfloor m/l \rfloor} ] 前缀积可以 得到区间积,快速幂求幂次。
算法标签
- 数论
- 莫比乌斯反演
- Fibonacci 数列
- 积性函数
- 数论分块
- 前缀积与逆元
- 线性筛
时间复杂度
- 预处理:
- 每次查询:(数论分块)
对于 是可行的。
代码总结
代码的核心是:
- 线性筛 和预处理 (Fibonacci)。
- 利用倍数枚举法计算 。
- 前缀积优化区间乘积。
- 查询时数论分块 + 快速幂。
这样就能高效求出所有格子的 Fibonacci 值的乘积。
- 1
信息
- ID
- 3058
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者