[莫比乌斯反演] 51Nod 1355 斐波那契的最小公倍数

来源:互联网 发布:yy协议软件手机版 编辑:程序博客网 时间:2024/06/03 00:03

现在我自己推不出来,看题解的。
http://blog.csdn.net/ZLH_HHHH/article/details/77587832
大概是考虑用经典的容斥写出答案的式子,考虑每个数对答案的贡献,然后需要反演一下算出贡献的式子。

#include<cstdio>#include<algorithm>using namespace std;typedef long long LL;const int N=1000000,maxv=1000005,MOD=1000000007;int n,fib[maxv],cnt[maxv],ctb[maxv],a[maxv],mu[maxv],p[maxv];LL ans;bool vis[maxv];void get_mu(){    mu[1]=1;    for(int i=2;i<=N;i++){        if(!vis[i]) p[++p[0]]=i, mu[i]=-1;        for(int j=1;j<=p[0]&&(LL)i*p[j]<=N;j++){            vis[i*p[j]]=true;            if(i%p[j]==0){ mu[i*p[j]]=0; break; }            mu[i*p[j]]=-mu[i];        }    }}int Pow(LL a,LL b){    LL res=1;    for(;b;b>>=1,a=a*a%MOD) if(b&1) res=(res*a)%MOD;    return res; }LL get(LL a,LL b){    if(b>=0) return Pow(a,b);    return Pow(Pow(a,-b),MOD-2);}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++){        int x; scanf("%d",&x);        if(x>=3) a[x]++;    }     for(int i=3;i<=N;i++)     for(int j=1;i*j<=N;j++) cnt[i]+=a[i*j];    get_mu();    for(int i=3;i<=N;i++)     for(int d=1;i*d<=N;d++) if(cnt[i*d]) ctb[i]+=mu[d];        fib[1]=1; for(int i=2;i<=N;i++) fib[i]=(fib[i-1]+fib[i-2])%MOD;    ans=1; for(int i=3;i<=N;i++)     ans=(ans*get(fib[i],ctb[i]))%MOD;    printf("%lld\n",ans);    return 0;}
阅读全文
0 0
原创粉丝点击