博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

51Nod.1244.莫比乌斯函数之和(杜教筛)

题目链接


map:

//杜教筛
#include<map>
#include<cstdio>
typedef long long LL;
const int N=5e6;

int mu[N+3],P[N+3],cnt;
bool Not_P[N+3];
std::map<LL,LL> sum;
//std::map<LL,LL>::iterator it;

void Init()
{
	mu[1]=1;
	for(int i=2;i<N;++i)
	{
		if(!Not_P[i]) P[++cnt]=i,mu[i]=-1;
		for(int j=1;j<=cnt&&i*P[j]<N;++j)
		{
			Not_P[i*P[j]]=1;
			if(!(i%P[j])) {mu[i*P[j]]=0; break;}
			mu[i*P[j]]=-mu[i];
		}
	}
	for(int i=2;i<N;++i) mu[i]+=mu[i-1];
}
LL Calc(LL n)
{
	if(n<N) return mu[n];
//	if((it=sum.find(n))!=sum.end()) return it->second;//效率是几乎一样的
	if(sum.count(n)) return sum[n];
	LL ans=1;
	for(LL nxt,i=2;i<=n;i=nxt+1)
		nxt=n/(n/i),ans-=(nxt-i+1)*Calc(n/i);
	return sum[n]=ans;
}

int main()
{
	Init();
	LL a,b;scanf("%lld%lld",&a,&b);
	printf("%lld",Calc(b)-Calc(a-1));

	return 0;
}

数组:(使用数组这个trick存的话 对于多组询问就要重新计算了)
但是据(rqy)说map实际用到的次数并不多,所以多次询问还是直接用map吧。
//比map还要慢一点

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
typedef long long LL;
const int N=5e6;

int mu[N+3],P[N+3],cnt;
LL sum2[15000],Max;
bool Not_P[N+3];

void Init()
{
	mu[1]=1;
	for(int i=2;i<Max;++i)
	{
		if(!Not_P[i]) P[++cnt]=i,mu[i]=-1;
		for(int j=1;j<=cnt&&i*P[j]<Max;++j)
		{
			Not_P[i*P[j]]=1;
			if(!(i%P[j])) {mu[i*P[j]]=0; break;}
			mu[i*P[j]]=-mu[i];
		}
	}
	for(int i=1;i<Max;++i) mu[i]+=mu[i-1];
}
const int EQU=-2333333;
LL Calc(LL n,LL mx)
{
	if(n<Max) return mu[n];
	if(sum2[mx/n]!=EQU) return sum2[mx/n];
	LL ans=1;
	for(LL nxt,i=2;i<=n;i=nxt+1)
		nxt=n/(n/i),ans-=(nxt-i+1)*Calc(n/i,mx);
	return sum2[mx/n]=ans;
}

int main()
{
	LL a,b;scanf("%lld%lld",&a,&b);
//	printf("%.3lf %.3lf\n",pow(a,0.667),pow(b,0.667));
	Max=pow(b,0.667), Init();
	std::fill(sum2,sum2+15000,EQU); LL ans1=Calc(b,b);
	std::fill(sum2,sum2+15000,EQU); LL ans2=Calc(a-1,a-1);
	printf("%lld",ans1-ans2);

	return 0;
}
posted @ 2018-01-25 11:20  SovietPower  阅读(223)  评论(0编辑  收藏  举报