【51nod 1355】 斐波那契的最小公倍数

nekko

2018-12-25 10:03:45

Personal

### 题目描述 设 $f_0=0,f_1=1$,且 $\forall i \ge 2$,有 $f_i=f_{i-1}+f_{i-2}$ 给定 $n$,以及一个长度为 $n$ 的数组 $a$ 求: $$\text{lcm}(f_{a_1},f_{a_2},f_{a_3},f_{a_4},\cdots,f_{a_n}) \bmod {1000000007}$$ $2 \le n \le 50000$ $1 \le a_i \le 10^6$ ### 题解 不妨手玩一下关于 $\text{lcm}$ 的性质…… $$\text{lcm}(a,b)=\frac{ab}{\gcd(a,b)}$$ $$\text{lcm}(a,b,c)=\frac{abc\gcd(a,b,c)}{\gcd(a,b)\gcd(b,c)\gcd(a,c)}$$ 推广到更一般的情况,即一个集合 $S$ 的 $\text{lcm}$: $$\text{lcm}(S)=\prod_{\emptyset \ne T \subseteq S} \gcd(T)^{\left( (-1)^{\mid T \mid + 1} \right)}$$ 之后就要去看一下斐波那契数列的性质咯 通过 [这道题](https://www.luogu.org/problemnew/show/P1306) 可以学习到一个关于斐波那契数列的很重要的性质: $$\gcd(f_i,f_j)=f_{\gcd(i,j)}$$ 于是就可以化简一下式子咯: $$ \begin{aligned} &\text{lcm}(f_{a_1},f_{a_2},f_{a_3},f_{a_4},\cdots,f_{a_n}) \\ =&\prod_{\emptyset \ne T \subseteq S} \gcd({f_{T}})^{\left( (-1)^{\mid T \mid + 1} \right)} \\ =&\prod_{\emptyset \ne T \subseteq S} f_{\gcd(T)}^{\left( (-1)^{\mid T \mid + 1} \right)} \\ \end{aligned} $$ 然而这个还是不太好做……因为有一个 $[\gcd(S)=d]$ 的限制…… 然而这个可以想到莫比乌斯反演那一套理论 $$f=g \times 1 \Leftrightarrow g=f \times \mu$$ 考虑在 $\prod$ 意义下的莫比乌斯反演…… $$f_n=\prod_{d \mid n} g_d \Leftrightarrow g_n=\prod_{d \mid n}f_d^{\mu(\frac{n}{d})}$$ 当然如果只是要计算 $g$的话,有: $$f_n=\prod_{d \mid n} g_d \Rightarrow g_n=\frac{f_n}{\prod_{d \mid n \wedge d \ne n}g_d}$$ 然后就可以通过枚举倍数来计算出 $g$ 了 于是现在式子就相当于这个了: $$ \begin{aligned} &\prod_{\emptyset \ne T \subseteq S} f_{\gcd(T)}^{\left( (-1)^{\mid T \mid + 1} \right)} \\ =&\prod_{\emptyset \ne T \subseteq S} \left(\prod_{d \mid \gcd(T)}g_d\right)^{\left( (-1)^{\mid T \mid + 1} \right)} \\ =&\prod_{d} g_d^{\sum_{\emptyset \ne T \subseteq S \wedge d \mid \gcd(T)}(-1)^{\mid T \mid + 1}} \end{aligned} $$ 考虑一个 $g_d$ 对答案的贡献,也就是指数上那个玩意,即: $$\sum_{\emptyset \ne T \subseteq S \wedge d \mid \gcd(T)} (-1)^{\mid T \mid +1}$$ 显然是实际有用的 $T$ 的并集是 $S'=\{x \mid \forall x \in S \wedge d \mid x\}$ 假设 $\mid S' \mid = n$,则有: $$ \begin{aligned} &\sum_{\emptyset \ne T \subseteq S \wedge d \mid \gcd(T)} (-1)^{\mid T \mid +1} \\ =&\sum_{i=1}^{n} {n \choose i} (-1)^{i+1} \\ =&(-1) \left(\sum_{i=1}^{n}{n \choose i}(-1)^{i}\right) \\ =&(-1) \left((1-1)^n-{n \choose 0} (-1)^{0}\right) \\ =&[n \ne 0] \end{aligned} $$ 也就是说,对于一个 $g_d$,只要 $\exists x \mid a_i$,那么 $g_d$ 就会对答案产生 $1$ 的贡献(注意最多产生一次) ### 代码 ``` cpp #include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e6 + 10, mod = 1e9 + 7; int n, mx, a[N]; ll fib[N], g[N], cnt[N], ans = 1; ll pw(ll a, ll b) { ll r = 1; for( ; b ; b >>= 1, a = a * a % mod) if(b & 1) r = r * a % mod; return r; } int main() { scanf("%d", &n); for(int i = 1 ; i <= n ; ++ i) scanf("%d", &a[i]), mx = max(mx, a[i]), cnt[a[i]] ++; fib[1] = g[1] = 1; for(int i = 2 ; i <= mx ; ++ i) g[i] = fib[i] = (fib[i - 1] + fib[i - 2]) % mod; for(ll i = 1 ; i <= mx ; ++ i) for(ll j = 2, inv = pw(g[i], mod - 2) ; i * j <= mx ; ++ j) g[i * j] = g[i * j] * inv % mod; for(ll i = 1 ; i <= mx ; ++ i) for(ll j = 1 ; i * j <= mx ; ++ j) if(cnt[i * j]) { ans = ans * g[i] % mod; break; } printf("%lld\n", (ans % mod + mod) % mod); } ```