[51Nod1355]斐波那契的最小公倍数

V.[51Nod1355]斐波那契的最小公倍数

引理1. 设 \(f_i\) 表示斐波那契数列中第 \(i\) 项,则 \(\gcd(f_i,f_j)=f_{\gcd(i,j)}\)

一种证明方法是打表

另一种证明方法是,首先有 \(f_{i+j}=f_{i−1}f_j+f_if_{j+1}\)(这个可以通过暴力拆斐波那契数得到)。显然,\(f_{i-1}\)\(f_i\)\(\gcd\)\(1\)\(f_{j+1}\)\(f_j\)\(\gcd\)\(1\)(这个是真的简单归纳就能得出),故 \(\gcd(f_{i+j},f_j)=\gcd(f_i,f_j)\)。发现这就是求 \(\gcd\) 的辗转相减法的形式,因此证毕。

引理2. \(\operatorname{lcm}\{\mathbb S\}=\prod\limits_{\mathbb{T\subseteq S}}\gcd\{\mathbb T\}^{(-1)^{|\mathbb T|+1}}\)

考虑对每一个质数进行minmax容斥。在枚举一个质数后,考虑 \(\text{lcm}\) 中该质数的次数,为 \(\max\limits_{x\in\mathbb S}\{d_x\}\),其中 \(d_x\)\(x\) 中此质数的次数。

于是 \(\max\limits_{x\in\mathbb S}\{d_x\}=\sum\limits_{\mathbb{T\subseteq S}}(-1)^{|T|+1}\min\limits_{x\in\mathbb T}\{d_x\}\)。在将其移回指数上后,便得到了上述结论。

结合引理1,2,我们得到

\[\operatorname{lcm}\{f_\mathbb S\}=\prod\limits_{\mathbb{T\subseteq S}}f_{\gcd\{\mathbb T\}}^{(-1)^{|\mathbb T|+1}} \]

现在考虑对于每个 \(\gcd\),有多少符合条件的 \(\mathbb T\),以及有多少个 \(|\mathbb T|\) 为奇,多少个为偶。

考虑我们现在强行构造出一个数列 \(g\) 满足 \(f_n\equiv\prod\limits_{d|n}g_d\pmod{10^9+7}\)。于是就有

\[\prod\limits_{\mathbb{T\subseteq S}}f_{\gcd\{\mathbb T\}}^{(-1)^{|\mathbb T|+1}}=\prod\limits_{\mathbb{T\subseteq S}}(\prod\limits_{d|\gcd\{\mathbb T\}}g_d)^{(-1)^{|\mathbb T|+1}}=\prod\limits_d(g_d)^{\sum\limits_{\mathbb{T\subseteq S},d|\gcd\{\mathbb T\}}(-1)^{|\mathbb T|+1}} \]

现在考虑把 \(g_d\) 的指数掏出来,是 \(\sum\limits_{\mathbb{T\subseteq S},d|\gcd\{\mathbb T\}}(-1)^{|\mathbb T|+1}\)

考虑 \(\mathbb S\) 中所有是 \(d\) 的倍数的数的数量,设其为 \(p\)。则上式等价于 \(\sum\limits_{k=1}^p\dbinom{p}{k}(-1)^{k+1}\)。显然,当 \(p\)\(0\) 时,此式为 \(0\);否则,其可被改写成 \(1+\sum\limits_{k=0}^p\dbinom{p}{k}(-1)^{k+1}\)。依据二项式定理,后面那一大坨,在 \(p>0\) 时为 \(0\)。故其就等价于 \([p>0]\),也即存在 \(d\) 的倍数。

于是问题转换为 \(\prod\limits_{\exists x\in\mathbb S,d|x}g_d\)。显然就可以简单求出。问题转换为如何构造 \(g\)

因为 \(f_n=\prod\limits_{d|n}g_d\),或许会想到狄利克雷卷积。但是狄利克雷卷积中是 \(\sum\) 而非 \(\prod\),因此不能使用。更好的方式是把除了 \(g_n\) 以外所有项全部移到另一边,得到 \(g_n=\dfrac{f_n}{\prod\limits_{d|n,d\neq n}g_d}\),可以 \(O(n\sqrt{n})\)\(O(n\log n)\) 地递推。

总时间复杂度可以做到 \(O(n\log n)\)

代码:

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int ksm(int x,int y=mod-2){int z=1;for(;y;y>>=1,x=1ll*x*x%mod)if(y&1)z=1ll*z*x%mod;return z;}
int n,m,a[50100],g[1001000],res=1;
bool occ[1001000];
int main(){
	scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]),m=max(m,a[i]),occ[a[i]]=true;
	g[0]=0,g[1]=1;for(int i=2;i<=m;i++)g[i]=(g[i-1]+g[i-2])%mod;
	for(int i=1;i<=m;i++){
		int inv=ksm(g[i]);
		for(int j=2*i;j<=m;j+=i)g[j]=1ll*g[j]*inv%mod;
		for(int j=i;j<=m;j+=i)if(occ[j]){res=1ll*res*g[i]%mod;break;}
	}
	printf("%d\n",res);
	return 0;
}

posted @ 2021-04-09 14:23  Troverld  阅读(113)  评论(0编辑  收藏  举报