bzoj 4176 Lucas的数论 莫比乌斯反演

来源:互联网 发布:win10系统优化批处理 编辑:程序博客网 时间:2024/05/27 21:08

ni=1nj=1d(i,j)=ni=1nj=1n2k=1[k|ij]
=ni=1nj=1n2k=1[kgcd(i,k)|j]=ni=1n2k=1ngcd(i,k)k
=nd=1ndi=1n2dk=1nk[gcd(i,k)=1]
=nd=1ndi=1nk=1nk[gcd(i,k)=1]
=nd=1ndi=1nk=1nkt|i,t|kμ(t)
=nt=1μ(t)nd=1ndti=1ntk=1nkt
=nt=1μ(t)nd=1ndtntk=1nkt
=nt=1μ(t)ntd=1ndtntk=1nkt
=nt=1μ(t)(ntd=1ndt)2

O(n)枚举nt , 一段区间的mu的和可以用3944的方法求。
(ntd=1ndt)2O(nt)求。

复杂度O(n34)

#include <bits/stdc++.h>using namespace std;#define ll long long#define M 15000000#define M1 15000010#define mod 1000000007bool ip[M1];int mu[M1],prime[M1/10];int cnt,n,ans;map<int,int>ma;void init(){    mu[1]=1;    for(int i=2;i<=M;i++)    {        if(!ip[i])prime[++cnt]=i,mu[i]=-1;        for(int j=1;j<=cnt&&i*prime[j]<=M;j++)        {            ip[i*prime[j]]=1;            if(i%prime[j]==0)break;            mu[i*prime[j]]=-mu[i];        }    }    for(int i=1;i<=M;i++)mu[i]+=mu[i-1];}int f(int x){    if(x<=M)return mu[x];    if(ma.count(x))return ma[x];    int ret=1;    for(int i=2,last;i<=x;i=last+1)    {        last=x/(x/i);        ret-=f(x/i)*(last-i+1);    }    return ma[x]=ret;}int cal(int x){    int ret=0;    for(int i=1,last;i<=x;i=last+1)    {        last=x/(x/i);        ret=(ret+(ll)(x/i)*(last-i+1)%mod)%mod;    }    return ret;}int main(){    //freopen("tt.in","r",stdin);    init();    scanf("%d",&n);    for(int i=1,last;i<=n;i=last+1)    {        last=n/(n/i);        int t=cal(n/i);        ans=(ans+(ll)(f(last)-f(i-1))*t%mod*t%mod)%mod;    }    printf("%d\n",(ans+mod)%mod);    return 0;}
0 0
原创粉丝点击