题意
给定 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)]=1−∑i=2n∑d|i,d<iμ(d)
采用和上一题一样的套路,变化得到:
M(n)=1−∑i=2n∑d=1⌊ni⌋μ(d)=1−∑i=2nM(⌊ni⌋)
然后就可以直接杜教筛了
复杂度
O( k∗n23 ), k <script type="math/tex" id="MathJax-Element-1249">k</script>为常数
代码
#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;
}