[51Nod1244]莫比乌斯函数之和

题意

  给定l,r,求ri=lμ(i)

解法

  和上一题差不多,只是推的式子不一样而已
  [n=1]=d|nμ(d)···
  由①得:μ(n)=[n=1]d|n,d<nμ(d)···
  令M(n)=ni=1μ(i),将②带入得到:

M(n)=i=1n[[i=1]d|i,d<iμ(d)]=1i=2nd|i,d<iμ(d)

  采用和上一题一样的套路,变化得到:
M(n)=1i=2nd=1niμ(d)=1i=2nM(ni)

  然后就可以直接杜教筛了

复杂度

O(kn23),k为常数

代码

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<map>
#define Rint register int
#define Lint long long int
using namespace std;
const int N=5000010;
bool vis[N];
int pri[N/10],miu[N],sum[N];
int cnt;
map<Lint,int> f;
void Prepare()
{
    miu[1]=1;
    for(int i=2;i<N;i++)
    {
        if( !vis[i] )   pri[++cnt]=i,miu[i]=-1;
        for(int j=1;j<=cnt;j++)
        {
            int x=pri[j]*i;
            if( x>=N )   break ;
            vis[x]=1;
            if( i%pri[j] )   miu[x]=-miu[i];
            else   break ;
        }
    }
    for(int i=1;i<N;i++)   sum[i]=sum[i-1]+miu[i];
}
int cal(Lint n)
{
    if( n<N )   return sum[n];
    if( f.count(n) )   return f[n];
    Lint x=2;int ret=1;
    while( x<=n )
    {
        Lint y=n/(n/x);
        ret-=(y-x+1)*cal(n/x),x=y+1;
    }
    return f[n]=ret;
}
int main()
{
    Lint l,r;
    Prepare();
    scanf("%lld%lld",&l,&r);
    printf("%d\n",cal(r)-cal(l-1));
    return 0;
}
posted @ 2018-02-12 17:25  清疚  阅读(107)  评论(0)    收藏  举报