题目大意
求n个斐波那契数的最小公倍数。
做法
首先斐波那契数列有性质
(fn,fm)=f(n,m)
具体证明不证了,烂大街的性质了。
构造数列g满足
fn=Πd|ngd
可以用莫比乌斯反演求出g
gn=Πd|nfμ(nd)d
接下来我们知道求lcm可以转化成一个容斥式子来求gcd,也是烂大街的性质。
lcm{fS}=ΠT⊆S,T≠∅f(−1)|T|+1gcd{T}
lcm{fS}=ΠT⊆S,T≠∅(Πd|gcd{T}gd)(−1)|T|+1
lcm{fS}=Πdg∑T⊆S,T≠∅,d|T(−1)|T|+1d
观察指数。
假如d在S中出现了t次,t为0的话这条式子显然为0,否则
∑ti=1Cit∗(−1)i+1
这个式子很经典了,t>=1它恒为1。
因此我们得到
lcm{fS}=Π∃a∈S,d|agd
这就好算了吧
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=1000000+10,mo=1000000007;
int f[maxn],g[maxn],mu[maxn],inv[maxn],pri[maxn];
bool bz[maxn];
int i,j,k,l,t,n,m,top,ans;
int quicksortmi(int x,int y){
if (!y) return 1;
int t=quicksortmi(x,y/2);
t=(ll)t*t%mo;
if (y%2) t=(ll)t*x%mo;
return t;
}
int main(){
//scanf("%d",&n);
n=1000000;
mu[1]=1;
fo(i,2,n){
if (!bz[i]) pri[++top]=i,mu[i]=-1;
fo(j,1,top){
if ((ll)i*pri[j]>n) break;
bz[i*pri[j]]=1;
if (i%pri[j]==0) break;
mu[i*pri[j]]=-mu[i];
}
}
fo(i,1,n) bz[i]=0;
f[0]=0;f[1]=1;
fo(i,2,n) f[i]=(f[i-1]+f[i-2])%mo;
fo(i,1,n) inv[i]=quicksortmi(f[i],mo-2);
fo(i,1,n) g[i]=1;
fo(i,1,n)
fo(j,1,n/i)
if (mu[j]==1) g[i*j]=(ll)g[i*j]*f[i]%mo;
else if (mu[j]==-1) g[i*j]=(ll)g[i*j]*inv[i]%mo;
scanf("%d",&m);
fo(i,1,m){
scanf("%d",&t);
bz[t]=1;
}
ans=1;
fo(i,1,n){
t=0;
fo(j,1,n/i) t|=bz[i*j];
if (t) ans=(ll)ans*g[i]%mo;
}
(ans+=mo)%=mo;
printf("%d\n",ans);
}