大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。遥想公瑾当年,小乔初嫁了,雄姿英发。羽扇纶巾,谈笑间,樯橹灰飞烟灭。故国神游,多情应笑我,早生华发。人生如梦,一尊还酹江月。

小奇学数论(loj 6235 区间素数个数)题解

min_25筛

昨天就想切这道题,结果晚上在划水,今天上午在考试,鸽到下午才做出来

本题做法有洲阁筛,min_25筛,某黑科技的素数筛等

注意到题目并未让我们输出具体有多少素数,所以可以用min_25筛

min_25筛的讲解在这里,自己看吧(捂脸

这里就借用这篇博客中的定义,谈此题的解法

设p为质数,区间质数个数为pl

定义f(p)=1,f(p*k)=0

求g(pl,n)

我们构造f'(i)=1,则函数f'满足:

  1. f'在质数处的取值与 f 相同。
  2. f′是完全积性函数。
  3. f'可以快速求前缀和。

故g的初值为

\(g(0,n)=n-1\)

g的递推式为

\(g(j,n)=\begin{cases}g(j-1,n)&p_j^2>n\\g(j-1,n)-(g(j,\lfloor\dfrac{n}{p_j}\rfloor)-(j-1))&p_j^2\le n\end{cases}\)

直接算即可。时间复杂度 \(O(\frac{N^{3/4}}{\log N})\)

是时候给出此题的最短(最快?)代码了!

我,WXL,永不打表!!!

#include<bits/stdc++.h>
using namespace std;

#define go(i,a,b) for(int i=a;i<=b;++i)
#define fo(i,a) for(int i=0;i<a;++i)
#define int long long
#define id(x) ((x)<=sq?id1[x]:id2[n/(x)])

const int N=330000;
typedef int aray[N];

int n,pl,tot,sq;
aray p,g,val,id1,id2;
bool vis[N];

void init(){
	sq=sqrt(n);
	go(i,2,sq){
		if(!vis[i]) p[pl++]=i;
		for(int *j=p;j<p+pl&&(*j)*i<=sq;++j){
			vis[(*j)*i]=1;
			if(i%(*j)==0) break;
		}
	}
	for(int i=1,j;i<=n;i=j+1){
		j=n/(n/i);
		val[++tot]=n/i;
		n/i<=sq?id1[n/i]=tot:id2[j]=tot;
		g[tot]=val[tot]-1;
	}
}

signed main(){
	//freopen("input.txt","r",stdin);
	cin>>n;
	init();
	fo(i,pl)
		go(j,1,tot){
			if(p[i]*p[i]>val[j]) break;
			g[j]-=g[id(val[j]/p[i])]-i;
		}
	printf("%lld",g[1]);
	return 0;
}
posted @ 2019-10-26 17:07  White_star  阅读(373)  评论(0编辑  收藏  举报
}