ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

min_25筛详解

2020-01-16 16:38:31  阅读:309  来源: 互联网

标签:prime 25 min primeorminp 质数 minp 详解 pj quad


扯淡

min_25筛是由min_25提出的求积性函数前缀和的亚线性算法,和一个叫“扩展埃氏筛”的东西有着微妙的关系。

至于是什么关系,我也不太清楚,反正有人说很像有人说就是一个东西(雾)

这段话并不是废话

约定

为了方便后面描述,这里写一些用到的约定和符号表示,以免产生恐惧

111被开除正整数籍 也就是说“前缀和”之类的都是从222开始,对答案所求的前缀和同样,最后手动加111

π(n)\pi(n)π(n)表示1n1 \sim n1∼n中质数个数的规模(其实问题不大,后面就懂了)

pip_ipi​表示第iii个质数,单独的ppp均表示质数

primeprimeprime表示质数集合 minp(i)minp(i)minp(i)表示iii的最小质因子

pcp^cpc表示一个只含一个质因子的数

流程

首先所求的函数f(n)f(n)f(n)需要满足:

  1. 是个积性函数
  2. 在质数处的取值f(p)f(p)f(p)是一个关于ppp的多项式。我们把这个多项式拆成若干单项式分别计算在相加,这样就变成了"f(p)f(p)f(p)的值是一个关于ppp的单项式",我们记为f(p)=pkf(p)=p^kf(p)=pk
  3. f(pc)f(p^c)f(pc)的值可以快速计算

首先考虑计算这个东西

i=2n[iprime]ik\sum_{i=2}^n[i\in prime]i^ki=2∑n​[i∈prime]ik

注意是iki^kik不是f(i)f(i)f(i),虽然这里还没有区别,但它们只是质数位置相等

首先既然叫扩展埃氏筛先回忆一下埃氏筛在干什么:开始写下所有正整数,然后从小到大,如果一个没被筛说明它是质数,用它筛掉后面的倍数

我们可以用这个思路计算上面的式子,先算出所有的和,再用质数筛掉所有合数项

g(n,j)g(n,j)g(n,j)表示用前jjj个质数筛了之后剩余项的和

g(n,j)=i=2n[iprimeorminp(i)>pj]ikg(n,j)=\sum_{i=2}^n[i \in prime \quad or\quad minp(i)>p_j]i^kg(n,j)=i=2∑n​[i∈primeorminp(i)>pj​]ik

和就是g(n,π(n))g(n,\pi(\sqrt{n}))g(n,π(n​))

注意合数的最小质因子不会超过n\sqrt nn​,所以如果pj2>np_j^2>npj2​>n有g(n,j)=g(n,j1)g(n,j)=g(n,j-1)g(n,j)=g(n,j−1)

对剩下情况考虑转移,即从g(n,j1)g(n,j-1)g(n,j−1)去掉被pjp_jpj​删掉的项

g(n,j1)=i=2n[iprimeorminp(i)pj]g(n,j-1)=\sum_{i=2}^n[i\in prime \quad or \quad minp(i)\geq p_j]g(n,j−1)=i=2∑n​[i∈primeorminp(i)≥pj​]

如果脑子转不过来,可以强行算

[iprimeorminp(i)pj][i\in prime \quad or \quad minp(i)\geq p_j][i∈primeorminp(i)≥pj​]且不满足[iprimeorminp(i)>pj][i \in prime \quad or\quad minp(i)>p_j][i∈primeorminp(i)>pj​]

[iprimeorminp(i)pj][i\in prime \quad or \quad minp(i)\geq p_j][i∈primeorminp(i)≥pj​]且[iprime][minp(i)pj][i \notin prime] 且 [minp(i)\leq p_j][i∈/​prime]且[minp(i)≤pj​]
综上
[iprime,minp(i)=pj][i \notin prime,minp(i)=p_j][i∈/​prime,minp(i)=pj​]

所以

g(n,j)=g(n,j1)i=2n[iprime,minp(i)=pj]ikg(n,j)=g(n,j-1)-\sum_{i=2}^n[i \notin prime,minp(i)=p_j]i^kg(n,j)=g(n,j−1)−i=2∑n​[i∈/​prime,minp(i)=pj​]ik

可以提一个pjp_jpj​出来,因为不能有质数,就把pjp_jpj​去掉,刚好是111

g(n,j)=g(n,j1)pjki=2npj[minp(i)pj]ikg(n,j)=g(n,j-1)-p_j^k\sum_{i=2}^{\lfloor\frac{n}{p_j}\rfloor}[minp(i)\geq p_j]i^kg(n,j)=g(n,j−1)−pjk​i=2∑⌊pj​n​⌋​[minp(i)≥pj​]ik

再次观察

g(n,j)=i=2n[iprimeorminp(i)>pj]ikg(n,j)=\sum_{i=2}^n[i \in prime \quad or\quad minp(i)>p_j]i^kg(n,j)=i=2∑n​[i∈primeorminp(i)>pj​]ik

发现可以拆成小于pjp_jpj​的质数和大于等于pjp_jpj​的所有数,第二个就是刚才的式子

g(n,j)=g(n,j1)pjk(g(npj,j1)i=1j1pik)g(n,j)=g(n,j-1)-p_j^k(g(\lfloor\frac{n}{p_j}\rfloor,j-1)-\sum_{i=1}^{j-1}p_i^k)g(n,j)=g(n,j−1)−pjk​(g(⌊pj​n​⌋,j−1)−i=1∑j−1​pik​)

注意nnn由于都是一直整除,所以只会有O(n)O(\sqrt n)O(n​)种取值,可以整除分块找出来强行离散化。在记录某个值vvv所在位置的时候,如果v>nv>\sqrt nv>n​,我们另开一个数组存到nv\lfloor\frac{n}{v}\rfloor⌊vn​⌋里面

然后后面只会用到最后一项,所以第二维可以滚掉

求答案时,设

S(n,j)=i=2n[minp(i)>pj]f(i)S(n,j)=\sum_{i=2}^n[minp(i)>p_j]f(i)S(n,j)=i=2∑n​[minp(i)>pj​]f(i)

分质数和合数分别计算

质数部分用ggg算出来的减去前jjj个

g(n,π(n))i=1jpig(n,\pi(\sqrt n))-\sum_{i=1}^jp_ig(n,π(n​))−i=1∑j​pi​

合数部分枚举最小质因子和它的次数

k=j+1pkne=1pkenf(pke)(S(npke,k)+[e>1])\sum_{k=j+1}^{p_k\leq\sqrt n}\sum_{e=1}^{p_k^e\leq n}f(p_k^e)(S(\lfloor\frac{n}{p_k^e}\rfloor,k)+[e>1])k=j+1∑pk​≤n​​e=1∑pke​≤n​f(pke​)(S(⌊pke​n​⌋,k)+[e>1])

[e>1][e>1][e>1]指如果指数大于111它本身就是合数,需要统计答案

两部分相加即可

总复杂度大概O(n23)O(n^{2\over3})O(n32​)常数较小,大约2s2s2s过1e101e101e10,3s3s3s过1e111e111e11

模板题

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>

#define MAXN 200005
using namespace std;
typedef long long ll;
const int MOD=1e9+7,INV6=(MOD+1)/6;
inline int add(const int& x,const int& y){return x+y>=MOD? x+y-MOD:x+y;}
inline int dec(const int& x,const int& y){return x<y? x-y+MOD:x-y;}
int np[MAXN],pl[MAXN],cnt;
inline void init(const int& N)
{
	np[1]=1;
	for (int i=2;i<=N;i++)
	{
		if (!np[i]) pl[++cnt]=i;
		int x;
		for (int j=1;(x=i*pl[j])<=N;j++)
		{
			np[x]=1;
			if (i%pl[j]==0) break;
		}
	}
}
ll val[MAXN];
int tot;
int g1[MAXN],g2[MAXN],sum1[MAXN],sum2[MAXN];
int key[MAXN],yek[MAXN];
ll n;
int m;
inline int getkey(const ll& v){return v<=m? key[v]:yek[n/v];}
int S(ll n,int j)
{
	if (pl[j]>=n) return 0;
	int k=getkey(n);
	int ans=dec(dec(g2[k],g1[k]),dec(sum2[j],sum1[j]));
	for (int k=j+1;k<=cnt&&(ll)pl[k]*pl[k]<=n;k++)
		for (ll e=1,pe=pl[k];pe<=n;e++,pe*=pl[k])
			ans=add(ans,pe%MOD*(pe%MOD-1)%MOD*(S(n/pe,k)+(e>1))%MOD);				
	return ans;
}
int main()
{
	scanf("%lld",&n);
	m=sqrt(n);
	init(m);
	for (ll l=1,r;l<=n;l=r+1)
	{
		r=n/(n/l);
		val[++tot]=n/l;
		int t=val[tot]%MOD;
		g1[tot]=((ll)t*(t+1)/2)%MOD-1;
		g2[tot]=(ll)t*(t+1)%MOD*(2*t+1)%MOD*INV6%MOD-1;
		if (val[tot]<=m) key[val[tot]]=tot;
		else yek[n/(n/l)]=tot;
	}
	for (int j=1;j<=cnt;j++)
	{
		for (int i=1;i<=tot&&(ll)pl[j]*pl[j]<=val[i];i++)
		{
			int k=getkey(val[i]/pl[j]);
			g1[i]=dec(g1[i],(ll)pl[j]*dec(g1[k],sum1[j-1])%MOD);
			g2[i]=dec(g2[i],(ll)pl[j]*pl[j]%MOD*dec(g2[k],sum2[j-1])%MOD);
		}		
		sum1[j]=add(sum1[j-1],pl[j]),sum2[j]=add(sum2[j-1],(ll)pl[j]*pl[j]%MOD);
	}
	printf("%d\n",S(n,0)+1);
	return 0;
}
Lstdo 发布了56 篇原创文章 · 获赞 3 · 访问量 4765 私信 关注

标签:prime,25,min,primeorminp,质数,minp,详解,pj,quad
来源: https://blog.csdn.net/luositing/article/details/104005161

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有