BZOJ 3944 Sum

题目链接:Sum

  嗯……不要在意……我发这篇博客只是为了保存一下杜教筛的板子的……

  你说你不会杜教筛?唐老师(其实我不认识)写了一篇讲的非常好的博客,看完应该就会了……

  这道题就是杜教筛板子题,也没什么好讲的……

  下面贴代码(不知道为什么我的常数就是大):

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 5664511

using namespace std;
typedef long long llg;

int pr[maxn],T,n,lp;
bool vis[maxn],vu[1300],vp[1300];
llg mu[maxn],phi[maxn],su[1300],sp[1300];

void pre(){
	mu[1]=phi[1]=1;
	for(int i=2;i<maxn;i++){
		if(!vis[i]) pr[++lp]=i,mu[i]=-1,phi[i]=i-1;
		for(int j=1;j<=lp && pr[j]*i<maxn;j++){
			vis[i*pr[j]]=1;
			if(i%pr[j]!=0) mu[i*pr[j]]=-mu[i],phi[i*pr[j]]=phi[i]*phi[pr[j]];
			else{phi[i*pr[j]]=phi[i]*pr[j];break;}
		}
	}
	for(int i=2;i<maxn;i++) mu[i]+=mu[i-1],phi[i]+=phi[i-1];
}

llg solveu(int x){
	if(x<maxn) return mu[x];
	if(vu[n/x]) return su[n/x];
	llg now=1; vu[n/x]=1;
	for(int i=2,nt=0;nt<x;i=nt+1) nt=x/(x/i),now-=(nt-i+1)*solveu(x/i);
	return su[n/x]=now;
}

llg solvep(llg x){
	if(x<maxn) return phi[x];
	if(vp[n/x]) return sp[n/x];
	llg now=x*(llg)(x+1); now>>=1;
	for(int i=2,nt=0;nt<x;i=nt+1) nt=x/(x/i),now-=(nt-i+1)*solvep(x/i);
	vp[n/x]=1; return sp[n/x]=now;
}

int main(){
	File("a");
	scanf("%d",&T); pre();
	while(T--){
		scanf("%d",&n);
		memset(vu,0,sizeof(vu));
		memset(vp,0,sizeof(vp));
		printf("%lld %lld
",solvep(n),solveu(n));
	}
	return 0;
}
原文地址:https://www.cnblogs.com/lcf-2000/p/6252885.html