51nod1244 莫比乌斯函数之和(杜教筛)

题面

传送门

题解

我……我忘记把预处理的块的大小调成(n^{frac{2}{3}})了……(仰天)

首先(mu*1=e)

然后杜教筛就行了

//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define IT map<ll,ll>::iterator
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
const int N=1e7+5;
bitset<N>vis;int p[N],mul[N];map<ll,ll>mp;
ll l,r;int m,sqr;
void init(int n){
	mul[1]=1;
	fp(i,2,n){
		if(!vis[i])p[++m]=i,mul[i]=-1;
		for(R int j=1;j<=m&&1ll*i*p[j]<=n;++j){
			vis[i*p[j]]=1;
			if(i%p[j]==0)break;
			mul[i*p[j]]=-mul[i];
		}
	}
	fp(i,2,n)mul[i]+=mul[i-1];
}
ll Mul(ll n){
	if(n<=sqr)return mul[n];
	IT it=mp.find(n);
	if(it!=mp.end())return it->second;
	ll res=1;
	for(ll i=2,j;i<=n;i=j+1)
		j=n/(n/i),res-=Mul(n/i)*(j-i+1);
	return mp[n]=res;
}
int main(){
//	freopen("testdata.in","r",stdin);
	scanf("%lld%lld",&l,&r),init(sqr=N-5);
	printf("%lld
",Mul(r)-Mul(l-1));
	return 0;
}
原文地址:https://www.cnblogs.com/bztMinamoto/p/10428043.html