首页 > 其他分享 >min25筛的常数优化&“多记一维”的艺术

min25筛的常数优化&“多记一维”的艺术

时间:2023-11-10 11:48:17浏览次数:29  
标签:pr le min25 u64 u32 一维 多记 mod

前置知识:min25 筛,即你要用 min25 筛通过板子题,不管写成啥样,不管常数多大,但是你要了解一点 min25

没有特殊说明的话有如下记号(大部分记号与 oi-wiki 一致):

  • \(x/y=\lfloor\frac{x}{y}\rfloor\)
  • \(\text{P}\) 为素数集合,\(p_k\) 表示第 \(k\) 小素数。特别地,令 \(p_{0} = 1\)。\(\text{lpf}(n)\) 表示 \(n\) 的最小素因子。

min25 筛说的是这样一个东西,记:

\(F_{\mathrm{pr}}(n) := \sum\limits_{2 \le p \le n,p\in \text{P}} f(p)\)
\(F_{k}(n) := \sum\limits_{2\le i\le n} [p_{k} \le \operatorname{lpf}(i)] f(i)\)

则 \(F_{k}(n)= \sum\limits_{\substack{k \le i \\ p_{i}^{2} \le n}} \sum\limits_{\substack{c \ge 1 \\ p_{i}^{c + 1} \le n}} \left(f\left(p_{i}^{c}\right) F_{i + 1}\left(n / p_{i}^{c}\right) + f\left(p_{i}^{c + 1}\right)\right) + F_{\mathrm{pr}}(n) - F_{\mathrm{pr}}(p_{k - 1})\)

接下来先上常数小的代码:

$\texttt{code}$
//落谷 P5325
//https://www.luogu.com.cn/problem/P5325
#include<bits/stdc++.h>
#define u32 unsigned int
#define u64 unsigned long long
#define u128 unsigned __int128
#define fr(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);
using namespace std;
const u32 N=2e5+5,M=227649,mod=1e9+7,inv2=(mod+1)/2,inv6=(mod+1)/6;
u32 m,cnt,pr[N],g[N][2],tot,vp[M][45];
u64 n,to[N],inv[N];
inline u64 div(u64 x,u32 y){return (u128)x*inv[y]>>64;}
inline constexpr u32 AD(u32 x,u32 y){return x+=y,x>=mod?x-mod:x;}
inline constexpr u32 S1(u64 x){x%=mod;return (u64)x*(x+1)%mod*inv2%mod;}
inline constexpr u32 S2(u64 x){x%=mod;return (u64)x*(x+1)%mod*(x<<1|1)%mod*inv6%mod;}
inline constexpr u32 ff(u64 x){x%=mod;return x*(x-1)%mod;}
inline u32 TO(u64 x){return x<=m?x:tot-(u64)((double)(n)/x)+1;}
u32 S(u64 x,u32 y)
{
	if(pr[y]>=x) return 0;u32 ans=g[TO(x)][0]+mod-g[pr[y]][0];u64 X;
	for(u32 i=y+1,e;i<=cnt&&(u64)pr[i]*pr[i]<=x;i++)
		for(e=1,X=div(x,pr[i]);X>=pr[i];e++,X=div(X,pr[i]))
			ans=(ans+vp[i][e+1]+(u64)vp[i][e]*S(X,i))%mod;
	return ans;
}
int main()
{
	scanf("%lld",&n);m=sqrt(n);
	for(u32 i=1;i<=m;i++) inv[i]=~0ull/i+1;
	for(u64 i=1,t=n;i<=n;i=n/t+1,t=n/i) to[++tot]=n/t,g[tot][0]=S2(to[tot])-1,g[tot][1]=S1(to[tot])-1;//一定要减去1的贡献!
	for(u32 i=2;i<=m;i++) if(g[i][0]^g[i-1][0])
	{
		pr[++cnt]=i;u32 t0=g[i-1][0]+mod,t1=g[i-1][1]+mod,pf=(u64)i*i%mod;
		for(u32 j=tot,t=TO(div(to[j],i));t>=i;t=TO(div(to[--j],i)))
			g[j][0]=(g[j][0]+(u64)pf*(t0-g[t][0]))%mod,
			g[j][1]=(g[j][1]+(u64)i*(t1-g[t][1]))%mod;
	}
	for(u32 i=1;i<=tot;i++) g[i][0]=AD(g[i][0],mod-g[i][1]);
	for(u32 i=1;i<=cnt;i++) for(u64 s=pr[i],e=1;s<=n*pr[i];s*=pr[i],e++) vp[i][e]=ff(s);
	printf("%d",AD(S(n,0),1));
	return 0;
}//n<=10^12 内不丢精度 

标签:pr,le,min25,u64,u32,一维,多记,mod
From: https://www.cnblogs.com/HaHeHyt/p/17823726.html

相关文章

  • Java小白学习记录--------常见的一维数组遍历方法
    一维数组:for循环遍历:int[]myArray={1,2,3,4,5};for(inti=0;i<myArray.length;i++){System.out.println("myArray["+i+"]="+myArray[i]);//输出数组中的每个元素} for-each循环遍历数组(增强for循环遍历)int[]myArray={1,2,3,4,5};......
  • 【进阶算法】一维数组的前缀和
    前缀和是指数组某个索引之前的所有元素的和,是一种重要的预处理手段,使用前缀和可以快速求出数组某一个区间的和。 示例:数组arr=[8,1,3,-2,5,0,-3,6],输入m个询问,每个询问输入一对l,r。对于每个询问,要求输出原数组中从第l个数到第r个数的和。比如,第1次询问,输入[0,2],需要输出1......
  • C语言入门之数组之一维和二维----小白
    今天的介绍C语言数组的概念。数组的分类一维数组和多维数组。一维数组和二维数组,这是我们今天主要介绍的两种。一数组的概念。数组是一组相同类型元素的集合,我们在前面介绍了数据类型。他可以将多个相同类型的数据,放到一起。1.数组的数据不能为0,至少要放一个元素。或者对他进行初始......
  • JavaScript树型数据与一维数组相互转换方式
     /***@description一维数组转树形数据**/exportconstarrToTree=(data=[],conf={})=>(((data,{id='id',parentId='parentId',children='children'})=>{letresult=[]if(!Array.isArray(data)){r......
  • 差分(一维)
    一、算法描述本篇文章介绍前缀和的逆运算,差分。什么是差分?差分是前缀和的逆运算,比如\(a[n]\)是原数组,\(s[n]\)是\(a[n]\)的前缀和数组,那么对于\(s[n]\)来说,\(a[n]\)就是\(s[n]\)的差分数组。假设原数组为\(a[n]\),\(b[n]\)为差分数组,那么他们之间的关系为:b[1......
  • 前缀和(一维)
    一、算法描述本篇文章我们来介绍一个简单的算法,前缀和。什么是前缀和?前缀和是某一个序列的前n项的和,可以理解为数学上的数列的前n项和。如果\(a\)和\(s\)分别是原数组和前缀和数组,那么应该有如下关系:s[1]=a[1];、s[2]=a[1]+a[2];、s[3]=a[1]+a[2]+a[3];......
  • c语言,一维数组指针
    @TOC前言今天我们讲一下一维数组指针。一、一维数组指针的定义:概述:数组指针,就是数组类型的指针。数组里面的每一个元素都是一个地址。可以让数组指针指向一个数组的地址,通过地址遍历数组的各个元素。定义一维数组指针的步骤:inta[5]={4,5,6,7,8};//定义一个数组int(*......
  • 基本差分算法:一维差分、二维差分
    1、一维差分首先要知道,差分是前缀和的逆运算,a1a2……an前缀和b1b2……bn差分以AcWing.797为例,题目要求如下:输入一个长度为n的整数序列。接下来输入m个操作,每个操作包含三个整数l,r,c,表示将序列中[l,r]之间的每个数加上c。请你输出进行完所有操作后的序......
  • 基本前缀和算法:一维前缀和、二维前缀和、子矩阵和
    1、一维前缀和以AcWing.795为例,题目要求如下:输入一个长度为N的整数序列。接下来再输入m个询问,每个询问输入一对l,r。对于每个询问,输出原序列中从第l个数到第r个数的和。输入格式第一行包含两个整数n和m。第二行包含n个整数,表示整数数列。接下来m行,每行包含两个整数l和r,表示一......
  • 使用maskbarcode.jar实现一维条形码
    1.在项目的WEB-INF下的lib目录添加maskbarcode.jar2.配置web.xml文件,代码如下:1.<?xmlversion="1.0"encoding="UTF-8"?>2.<web-appversion="2.5"3.xmlns="http://java.sun.com/xml/ns/javaee"4.xmlns:xsi="h......