一种质数筛法

考虑 min_25 筛,可以做到 O(n0.75logn)

但是 n1013,无法通过。

考虑值域分治,使用树状数组处理 1B1 的质数前缀个数。可以把筛质数改成 O(nloglogn) 筛,会方便一点,每次可以顺便地扫描每个最小质因子是当前枚举质数的数。

时间 O(B1logB1+nB1logn),取 B1=n23log43n 可以做到 O(n23log13n)

考虑 1B2 直接暴力做,B2+1B1 用树状数组。

B2=n6, B1=(nlogn)23 时做到 O((nlogn)23)

点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define pir pair<ll,ll>
#define fi first
#define se second
#define mkp make_pair
#define pb push_back
using namespace std;
const ll maxn=4e6+10;
ll n,g[maxn<<1],id1[maxn],id2[maxn],sq,w[maxn<<1],len,sum[maxn],cnt;
int tree[maxn*10];
bool vis[maxn*10];
ll B1,B2;
void add(ll x,ll v){
	while(x<=B1){
		tree[x]+=v; x+=x&-x;
	}
}
ll ask(ll x){
	ll v=0;
	while(x){
		v+=tree[x]; x-=x&-x;
	} return v;
}
ll Id(ll x){
	if(x<=sq) return id1[x];
	return id2[n/x];
}
ll Get(ll x){
	if(x<=B2) return sum[x];
	if(x<=B1) return ask(x)+sum[B2];
	return g[Id(x)];
}
int main(){
	scanf("%lld",&n);
	B1=pow(n/log2(n),0.66), B2=sqrt(n);
	B1=max(B1,B2);
	for(ll i=1;i<=n;i++){
		ll d=n/i, r=n/d;
		if(d<=B1) break; 
		w[++len]=d;
		g[len]=d; i=r;
		if(d<=sq) id1[d]=len;
		else id2[n/d]=len;
		i=r;
	}
	for(ll i=1;i<=B2;i++) sum[i]=i;
	for(ll i=B2+1;i<=B1;i++) add(i,1);
	for(ll i=2;i*i<=n;i++){
		if(vis[i]) continue;
		++cnt;
		ll t=i*i; double inv=1.0/i;
		for(ll j=1;j<=len&&w[j]>=t;j++)
			g[j]-=Get(w[j]*inv+1e-6)-cnt;
		for(ll j=B2;j>=t;j--) sum[j]-=sum[(int)(j*inv+1e-6)]-cnt;
		for(ll j=i*i,o=max(B1,sq);j<=o;j+=i)
			if(!vis[j]){
				vis[j]=true;
				if(j>B2&&j<=B1) add(j,-1);
			}
	}
	printf("%lld",Get(n)-1);
	return 0;
}

出处:https://www.cnblogs.com/Sktn0089/p/18055068

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   Lgx_Q  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示