杜教筛的介绍

杜教筛是圈内的一个老师发明的,有狄利克雷卷积推出来的一个算f(n)的前缀和的比较快的算法大概在O(2/3)范围内

通常令g=1算一些特殊函数的前缀和:

莫比乌斯函数

cosnt int maxn=1e5+9;
vector<int>primes;
bool vis<maxn>;
ll mu[maxn],smu[maxn];
unordered_map<ll ,ll >memu;
void init(){
	mu[1]=1;
	for(int i=2;i<maxn;i++){
		if(!vis[i])primes.push_back(i),mu[i]=-1;
		for(auto p: primes){
			if(p*i>maxn)break;
			vis[i*p]=1;
			if(i%p==0)[i*p]=0;
			else mu[i*p]=mu[i]*mu[p];
		}
	}
	for(int i=1;i<maxn;i++){
		smu[i]=smu[i-1]+mu[i];
	} 
}
int s_mu(int n){
	if(n<maxn)return smu[n];
	if(memu.count(n))return memu[n];
	ll ans=1;
	for(int l=2,r;l<=maxn;l=r+1){
		r=n/(n/l);
		ans-=(r-l+1)*(s_mu(n/l));
	}
    memu[n]=ans;
    return ans;
}

 欧拉函数

void phiinit(){
	phi[1]=1;
	for(int i=2;i<maxn;i++){
		if(!vis[i])primes.push_back(i),phi[i]=i-1;
		for(auto p: primes){
			if(p*i>maxn)break;
			vis[i*p]=1;
			phi[i*p]=phi[i]*phi[p];
			if(i%p==0)phi[i*p]=i*phi[p];
		}
	}
	for(int i=1;i<maxn;i++){
		sphi[i]=sphi[i-1]+phi[i];
	} 
}
int s_phi(int n){
	if(n<maxn)return smu[n];
	if(memu.count(n))return mephi[n];
	ll ans=n*(n+1)/2;
	for(int l=2,r;l<=maxn;l=r+1){
		r=n/(n/l);
		ans-=(r-l+1)*(s_phi(n/l));
	}
    mephi[n]=ans;
    return ans;
}

这里我先对函数进行了线性筛法,然后保存前缀和,对大于maxn的数用杜教筛计算,这里算后半部分的过程是利用了整体分快的思想,加大时间效率同时用哈希map对去过的数进行一个记忆化。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值