51nod1355 斐波那契的最小公倍数

来源:互联网 发布:淘宝查销售额 编辑:程序博客网 时间:2024/06/06 20:24

首先我们可以知道fn+m=fn1fm+fnfm+1,这一点可以用数学归纳法证明。于是我们有gcd(fn+m,fm)=gcd(fn,fm)。进一步地,gcd(fn,fm)=fgcd(n,m)
g=f×1,那么根据最大最小值反演我们有

lcm(fS)=TSgcd(fT)(1)|T|+1=TSfgcd(T)(1)|T|+1=dgdTS,d|gcd(T)(1)|T|+1=si,d|sigd

复杂度O(nm+mlogm)

#include<cstdio>#include<algorithm>using namespace std;#define LL long longconst int maxm=1000010,maxn=50010,p=1000000007;int f[maxm],g[maxm],a[maxn],vis[maxm],n,m;int inc(int x,int y){    x+=y;    return x>=p?x-p:x;}int pow(int b,int k){    int r=1;    for (;k;k>>=1,b=(LL)b*b%p)        if (k&1) r=(LL)r*b%p;    return r;}int main(){    int x,ans=1;    scanf("%d",&n);    for (int i=1;i<=n;i++) scanf("%d",&a[i]),m=max(m,a[i]);    f[1]=g[1]=1;    for (int i=2;i<=m;i++) f[i]=g[i]=inc(f[i-1],f[i-2]);    for (int i=1;i<=m;i++)    {        x=pow(g[i],p-2);        for (int j=i*2;j<=m;j+=i)            g[j]=(LL)g[j]*x%p;    }    for (int i=1;i<=n;i++)        for (int j=1;(LL)j*j<=a[i];j++)            if (a[i]%j==0) vis[j]=vis[a[i]/j]=1;    for (int i=1;i<=m;i++)        if (vis[i]) ans=(LL)ans*g[i]%p;    printf("%d\n",ans);}
原创粉丝点击