Min_25筛_min25 筛学习笔记-程序员宅基地

以前多次学习 Min_25筛,却一直一直不能透彻理解他

这挺让我沮丧的,本来不想写这篇博文,现在看来不写不行


Min_25筛

Min_25筛 是用来求解积性函数前缀和的快速筛法

但他对积性函数有一定要求,要求 f ( x ) , x ∈ P r i m e f(x),x\in Prime f(x),xPrime 是一个简单多项式,且 f ( x k ) , x ∈ P r i m e f(x^k),x\in Prime f(xk),xPrime 可以快速计算

Min_25筛的算法过程分为两步,先求质数的 f ( x ) f(x) f(x) 的和,再求 f ( x ) f(x) f(x) 的和也就是答案。


求质数的 f f f 的和

g ( x ) g(x) g(x) 表示把 x x x 当作质数时计算 f ( x ) f(x) f(x) 得到的结果。

G ( i , j ) , i = ⌊ n / d ⌋ G(i,j),i=\lfloor n/d\rfloor G(i,j),i=n/d 表示在前 i i i 个数中,没有被前 j j j 个质数筛掉数的 g g g 的和。

那么一开始 G ( i , 0 ) = ∑ k = 2 i g ( k ) G(i,0)=\sum_{k=2}^ig(k) G(i,0)=k=2ig(k) 。我们要保留的 g g g 都是质数的 g g g ,就要把合数的 g g g 筛走。

从小到大枚举质数 P j P_j Pj ,把最小质因子恰好为 P j P_j Pj 的那些合数的 g g g G G G 中去掉,枚举 ≥ P j 2 \ge P_j^2 Pj2 i i i G ( i , j ) G(i,j) G(i,j) 要减去 G ′ ( ⌊ i / P j ⌋ , j − 1 ) − ∑ k ≤ j − 1 g ( P k × P j ) G'(\lfloor i/P_j\rfloor,j-1)-\sum_{k\le j-1}g(P_k\times P_j) G(i/Pj,j1)kj1g(Pk×Pj) G ′ G' G 就是 ∑ g ( i ⋅ P j ) \sum g(i\cdot P_j) g(iPj)

最后的 G ( n , ∣ P ∣ ) G(n,|P|) G(n,P) 就是质数的 f f f 的和。


f f f 的和

F ( i , j ) , i = ⌊ n / d ⌋ F(i,j),i=\lfloor n/d\rfloor F(i,j),i=n/d 表示表示在前 i i i 个数中,最小质因子 ≥ P j \ge P_j Pj f f f 的和。 F ( n , ∣ P ∣ + 1 ) = 0 F(n,|P|+1)=0 F(n,P+1)=0

因为已经求了 G G G 的答案,现在只需要把合数的 f f f 加上去即可。从大到小枚举 P j P_j Pj ,把最小质因子恰好为 P j P_j Pj 的那些合数的 f f f 加到 F F F 中去,枚举 ≥ P j 2 \ge P_j^2 Pj2 i i i ,再枚举 P j e + 1 ≤ i P_j^{e+1}\le i Pje+1i e e e ,也就是那些合数中 P j P_j Pj 的指数。 F ( i , k ) , k ≤ j F(i,k),k\le j F(i,k),kj, 要加上 f ( P j e ) ⋅ F ( ⌊ i / P j e ⌋ , j + 1 ) + f ( P j e + 1 ) f(P_j^e)\cdot F(\lfloor i/P_j^e\rfloor,j+1)+f(P_j^{e+1}) f(Pje)F(i/Pje,j+1)+f(Pje+1)

f f f 的和就是 F ( n , 1 ) + 1 F(n,1)+1 F(n,1)+1


总结

G ( i , j ) = { G ( i , j − 1 ) P j 2 > i G ( i , j − 1 ) − G ′ ( ⌊ i / P j ⌋ , j − 1 ) + ∑ k ≤ j − 1 g ( P k × P j ) P j 2 ≤ i G(i,j)= \begin{cases} G(i,j-1) &P_j^2> i \\ G(i,j-1)-G'(\lfloor i/P_j\rfloor,j-1)+\sum_{k\le j-1}g(P_k\times P_j) &P_j^2\le i \\ \end{cases} G(i,j)={ G(i,j1)G(i,j1)G(i/Pj,j1)+kj1g(Pk×Pj)Pj2>iPj2i

F ( n , j ) = ∑ i ≥ j f ( P i ) + ∑ k ≥ j ∑ e f ( P k e ) F ( n / P k e , k + 1 ) + f ( P k e + 1 ) F(n,j)=\sum_{i\ge j}f(P_i)+\sum_{k\ge j}\sum_{e}f(P_k^e)F(n/{P_k^e},k+1)+f(P_k^{e+1}) \\ F(n,j)=ijf(Pi)+kjef(Pke)F(n/Pke,k+1)+f(Pke+1)


洛谷的板题

#include <bits/stdc++.h>
#define N 1000006
using namespace std;
typedef long long ll;
const ll mod=1e9+7,inv2=5e8+4,inv3=(mod+1)/3;
ll pri[N],num,sp1[N],sp2[N];
ll n,sqr,tot,g[N],gg[N],w[N],id1[N],id2[N];
bool tag[N];
void mo(ll &x){
     x=(x%mod+mod)%mod; }
ll find_pos(ll x){
     return x<=sqr?id1[x]:id2[n/x]; }
void init(ll n){
    
	tag[1]=1;
	for(ll i=1;i<=n;i++){
    
		if(!tag[i]){
    
			pri[++num]=i;
			sp1[num]=(sp1[num-1]+i)%mod;
			sp2[num]=(sp2[num-1]+1ll*i*i)%mod;
		}
		for(ll j=1;j<=num&&pri[j]*i<=n;j++){
    
			tag[i*pri[j]]=1;
			if(i%pri[j]==0) break;
		}
	}
}
ll S(ll x,ll y){
     // 前 x 个数中,最小质因数大于 pri_y 的数的函数和 
	if(pri[y]>=x) return 0;
	ll k=find_pos(x);
	ll res=(gg[k]-g[k]+mod-(sp2[y]-sp1[y])+mod)%mod,pe,xx;
//	cout<<res<<'\n';
	for(ll i=y+1;i<=num&&pri[i]*pri[i]<=x;i++){
    
		xx=pe=pri[i];
		for(ll e=1;pe<=x;pe=pe*pri[i],xx=pe%mod,e++)
			(res+=xx*(xx-1)%mod*(S(x/pe,i)+(e!=1))%mod)%=mod; //把合法的合数加回来 
	}
//	cout<<res<<'\n';
	return res;
}
int main(){
    
	cin>>n;
	sqr=sqrt(n);
	init(sqr);
	for(ll l=1,r;l<=n;l=r+1){
    
		r=n/(n/l);
		w[++tot]=n/l;
		g[tot]=w[tot]%mod;
		gg[tot]=g[tot]*(g[tot]+1)/2%mod*(2*g[tot]+1)%mod*inv3%mod;
		g[tot]=g[tot]*(g[tot]+1)/2%mod;
		g[tot]--,gg[tot]--;
		if(w[tot]<=sqr) id1[w[tot]]=tot;
		else id2[n/w[tot]]=tot;
	} //初始化 现在的 G 数组表示没有被前 0 个质数筛掉的 g 的和
	
	ll k;
	for(ll i=1;i<=num;i++){
     //筛 
		for(ll j=1;j<=tot&&pri[i]*pri[i]<=w[j];j++){
    
			k=find_pos(w[j]/pri[i]);
			mo(g[j]-=g[k]*pri[i]%mod-sp1[i-1]*pri[i]%mod);
			mo(gg[j]-=pri[i]*pri[i]%mod*(gg[k]-sp2[i-1]+mod)%mod);
		} 
//		cout<<g[1]<<'\n';
	} 
	cout<<(S(n,0)+1)%mod;
}

【LibreOJ #6053】
【JZOJ 5683】【GDSOI2018模拟4.22】
【51NOD 1847】
【51NOD 1965】

我是在 这里 学的

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/RA100FDM/article/details/113849652

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签