[51Nod1355]斐波那契的最小公倍数
V.[51Nod1355]斐波那契的最小公倍数
引理1. 设 表示斐波那契数列中第 项,则 。
一种证明方法是打表
另一种证明方法是,首先有 (这个可以通过暴力拆斐波那契数得到)。显然, 与 的 为 , 与 的 为 (这个是真的简单归纳就能得出),故 。发现这就是求 的辗转相减法的形式,因此证毕。
引理2. 。
考虑对每一个质数进行minmax容斥。在枚举一个质数后,考虑 中该质数的次数,为 ,其中 为 中此质数的次数。
于是 。在将其移回指数上后,便得到了上述结论。
结合引理1,2,我们得到
现在考虑对于每个 ,有多少符合条件的 ,以及有多少个 为奇,多少个为偶。
考虑我们现在强行构造出一个数列 满足 。于是就有
现在考虑把 的指数掏出来,是 。
考虑 中所有是 的倍数的数的数量,设其为 。则上式等价于 。显然,当 为 时,此式为 ;否则,其可被改写成 。依据二项式定理,后面那一大坨,在 时为 。故其就等价于 ,也即存在 的倍数。
于是问题转换为 。显然就可以简单求出。问题转换为如何构造 。
因为 ,或许会想到狄利克雷卷积。但是狄利克雷卷积中是 而非 ,因此不能使用。更好的方式是把除了 以外所有项全部移到另一边,得到 ,可以 或 地递推。
总时间复杂度可以做到 。
代码:
#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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?