「学习笔记」Min25筛

前言

周指导今天模拟赛五分钟秒第一题,十分钟说第二题是 \(\text{Min25}​\) 筛板子题,要不是第三题出题人数据范围给错了,周指导十五分钟就 \(\text{AK}​\) 了,为了向 \(\text{AK}​\)王 学习,真诚的膜拜他,接受红太阳的指导,下午就学习了一下 \(\text{Min25}​\) 筛。

简介

如果 \(f(n)\) 是一个积性函数,且 \(f(n)\) 是一个关于 \(n\) 的简单多项式,并可以快速算出 \(f(p^k),\ p\text{ is prime, } k \geq 0\) 的值,那么大概可以用 \(\text{Min25}\) 筛在 \(\mathcal O(\frac{n^\frac{3}{4}}{log_n})\) 求出 \(\sum_{i=1}^nf(i)\) 的值。

算法

首先令 \(s\) 为所有 \(i\in[1,n], \lfloor\frac{n}{i}\rfloor\) 的集合,并试图预处理出 \(\forall x \in s \sum_{i=2}^x [i\text{ is prime}] f(i)\)

可能当 \(x\) 不是质数的时候,\(f(x)\) 不太好求,我们先假装所有数都是质数,然后用类似埃式筛法的过程把不是质数的 \(f(x)\) 值给筛掉。

具体的算法之前,先定义一些东西:

令 \(P=\{prime_1\dots prime_m\}\) 表示前 \(m\) 个质数的集合,并且 \(prime_{m+1}>\sqrt n\) 。

令 $g(n,k) ={\sum_{i=2}^n[i \text{ is prime}\text{ or } minp(i)>prime_k]}f(i) $ 表示前 \(n\) 个数中满足是质数或者最小质因子大于第 \(k\) 个质数的数假装它为质数求出来的 \(f(x)\) 之和。

\(g(n, k)​\) 的本质是筛掉了前 \(n​\) 个数筛去前 \(k​\) 个质数的倍数后剩下的那些数的 \(f(x)​\) 之和,显然,\(g(S,m)​\) 就是要预处理的东西。

可以通过这个东西求 \(g\) 了

\[g(n,k) = g(n,k-1)\ \ \ \ \ \ \text{if } prime_k > \sqrt n \\
g(n,k) = g(n,k-1)-f(prime_k)\times [g(\lfloor\frac{n}{prime_k}\rfloor,k-1)-\sum_{i=1}^{k-1} f(prime_i)]\ \ \ \ \ \ \text{if } prime_k \leq \sqrt n
\]

第一个转移显然,\(prime_k​\) 筛不掉任何数了,第二个转移考虑把所有在前 \(k-1​\) 轮最小质因子不为 \(prime_k​\) 的数贡献减掉,因为 \(f(x)​\) 是积性的直接搞就好了,因为 \(g(n,k)​\) 仍然要保留前 \(k-1​\) 个质数的贡献,所以还要加回来。

现在已经预处理出了 \(\forall x \in s \sum_{i=2}^x [i\text{ is prime}] f(i)​\) 的值,也就是我们求出了质数的答案,接下来通过从小到大加入质因子来求出合数的答案。

令 \(S(n,k)=\sum_{i=2}^n [minp(i)\geq k] f(i)\) ,这里的 \(f(i)\) 就是真实的值了,不假装他是质数,那么答案就是 \(f(1)+S(n,1)\) 。

质数的贡献之前已经算出来了,就是 \(g(n,m)-\sum_{i=1}^{k-1}f(prime_i)\)。

考虑枚举每个数的最小质因子以及它们幂次得到合数的转移

\[S(n,k)=g(n,m)-\sum_{i=1}^{k-1}f(prime_i)+\sum_{j=k}^m\sum_{t=1}^{prime_{j}^{t+1}\leq \ n}S(\lfloor\frac{n}{prime_j^t}\rfloor,j+1)\times f(prime_{j}^t)+f(prime_j^{t+1})
\]

其中 \(S(\lfloor\frac{n}{prime_j^t}\rfloor,j+1)\times f(prime_{j}^t)\) 算的是后面还有别的质因子的情况,\(f(prime_j^{t+1})\) 算的是后面没有别的质因子的情况,可以感性理解一下。

例题

「Loj6235」 区间素数个数

求 \([1,n]\) 的素数个数,\(n \leq10^{11}\)

令 \(f(x)\) 当 \(x\) 是质数的时候为 \(1\) ,\(x\) 是其它数的时候为 \(0\) ,虽然不满足这个东西是一个关于 \(x\) 的简单多项式,但是只求 \(f\) 是质数的时候的答案显然是对的,\(g(n,m)\) 就是答案。

code

/*program by mangoyang*/
#include <bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int ch = 0, f = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
#define ID(x) ((x) <= T ? id[0][(x)] : id[1][n/(x)])
const int N = 1000005;
ll prime[N], id[2][N], a[N], g[N], n, m, tot, T;
int b[N];
int main(){
read(n), T = sqrt(n);
for(ll l = 1; l <= n; l = n / (n / l) + 1){
a[++m] = n / l, g[m] = a[m] - 1;
id[a[m]<=T?0:1][a[m]<=T?a[m]:n/a[m]] = m;
}
for(int i = 2; i <= T; i++){
if(!b[i]) prime[++tot] = i;
for(int j = 1; j <= tot && i * prime[j] <= T; j++){
b[i*prime[j]] = 1;
if(i % prime[j] == 0) break;
}
}
for(int i = 1; i <= tot; i++)
for(int j = 1; j <= m && prime[i] * prime[i] <= a[j]; j++)
g[j] -= g[ID(a[j]/prime[i])] - (i - 1);
cout << g[ID(n)] << endl;
return 0;
}

「51NOD1222」 最小公倍数计数

令 \(f(n)=\sum_{i=1}^n\sum_{j=i}^n [\text{lcm}(i,j)=n]\),求 \(\sum_{i=a}^b f(i),a\leq b\leq 10^{11}\) 。

首先先令 \(f'(n)=\sum_{i=1}^n\sum_{j=1}^n[\text{lcm}(i,j)=n]\) ,显然 \(f(n)=\frac{f'(n)+n}{2}\) 。

\[\sum_{i=1}^n\sum_{j=1}^n[\text{lcm}(i,j)=n]\\
=\sum_{i|n}^n\sum_{j|n}^n[\frac{ij}{\gcd(i,j)}=n] \\
=\sum_{i|n}^n\sum_{j|n}^n[ij=\gcd(ni,nj)] \\
=\sum_{i|n}^n\sum_{j|n}^n[\gcd(\frac{n}{i},\frac{n}{j})=1] \\
=\sum_{i|n}^n\sum_{j|n}^n[\gcd(i,j)=1] \\
=\sum_{d|n}2^\omega(d)
\]

最后一步考虑组合意义,每一种质因子,要么全部归 \(i\) 要么全部归 \(j\) ,然后你会发现,\(f'(n)\) 是一个积性函数,且满足 \(f(prime_i^k)=2k+1\) ,直接 \(\text{Min25}\) 筛即可。

code

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N = 1000005;
namespace Min25{
#define id(x) ((x) <= T ? id1[x] : id2[n/(x)])
ll prime[N];
int b[N], tot, id1[N], id2[N], m;
ll a[N], g[N], T, n;
inline void init(){
m = tot = 0, T = sqrt(n + 0.5);
for(int i = 2; i <= T; i++){
if(!b[i]) prime[++tot] = i;
for(int j = 1; j <= tot && i * prime[j] <= T; j++){
b[i*prime[j]] = 1;
if(i % prime[j] == 0) break;
}
}
for(ll l = 1; l <= n; l = n / (n / l) + 1){
a[++m] = n / l;
if(a[m] <= T) id1[a[m]] = m; else id2[n/a[m]] = m;
g[m] = 3ll * (a[m] - 1);
}
for(int j = 1; j <= tot; j++)
for(int i = 1; i <= m && prime[j] * prime[j] <= a[i]; i++){
g[i] -= g[id(a[i]/prime[j])] - 3ll * (j - 1);
}
}
inline ll solve(ll a, ll b){
if(a < prime[b]) return 0;
ll ans = g[id(a)] - 3 * (b - 1);
for(int j = b; j <= tot && prime[j] * prime[j] <= a; j++)
for(ll p = prime[j], t = 1; p * prime[j] <= a; t++, p = p * prime[j])
ans += solve(a / p, j + 1) * (2 * t + 1) + 2 * t + 3;
return ans;
}
inline ll gao(ll x){
if(x == 0) return 0;
if(x == 1) return 1;
n = x, init();
return (solve(n, 1) + 1 + n) / 2ll;
}
}
int main(){
ll a, b;
cin >> a >> b;
cout << Min25::gao(b) - Min25::gao(a - 1) << endl;
return 0;
}

「学习笔记」Min25筛的更多相关文章

  1. 「学习笔记」min_25筛

    前置姿势 魔力筛 其实不看也没关系 用途和限制 在\(\mathrm{O}(\frac{n^{0.75}}{\log n})\)的时间内求出一个积性函数的前缀和. 所求的函数\(\mathbf f(x ...

  2. 「学习笔记」FFT 之优化——NTT

    目录 「学习笔记」FFT 之优化--NTT 前言 引入 快速数论变换--NTT 一些引申问题及解决方法 三模数 NTT 拆系数 FFT (MTT) 「学习笔记」FFT 之优化--NTT 前言 \(NT ...

  3. 「学习笔记」FFT 快速傅里叶变换

    目录 「学习笔记」FFT 快速傅里叶变换 啥是 FFT 呀?它可以干什么? 必备芝士 点值表示 复数 傅立叶正变换 傅里叶逆变换 FFT 的代码实现 还会有的 NTT 和三模数 NTT... 「学习笔 ...

  4. 「学习笔记」Treap

    「学习笔记」Treap 前言 什么是 Treap ? 二叉搜索树 (Binary Search Tree/Binary Sort Tree/BST) 基础定义 查找元素 插入元素 删除元素 查找后继 ...

  5. 「学习笔记」字符串基础:Hash,KMP与Trie

    「学习笔记」字符串基础:Hash,KMP与Trie 点击查看目录 目录 「学习笔记」字符串基础:Hash,KMP与Trie Hash 算法 代码 KMP 算法 前置知识:\(\text{Border} ...

  6. 「学习笔记」wqs二分/dp凸优化

    [学习笔记]wqs二分/DP凸优化 从一个经典问题谈起: 有一个长度为 \(n\) 的序列 \(a\),要求找出恰好 \(k\) 个不相交的连续子序列,使得这 \(k\) 个序列的和最大 \(1 \l ...

  7. 「学习笔记」ST表

    问题引入 先让我们看一个简单的问题,有N个元素,Q次操作,每次操作需要求出一段区间内的最大/小值. 这就是著名的RMQ问题. RMQ问题的解法有很多,如线段树.单调队列(某些情况下).ST表等.这里主 ...

  8. 「学习笔记」递推 & 递归

    引入 假设我们想计算 \(f(x) = x!\).除了简单的 for 循环,我们也可以使用递归. 递归是什么意思呢?我们可以把 \(f(x)\) 用 \(f(x - 1)\) 表示,即 \(f(x) ...

  9. 「学习笔记」动态规划 I『初识DP』

    写在前面 注意:此文章仅供参考,如发现有误请及时告知. 更新日期:2018/3/16,2018/12/03 动态规划介绍 动态规划,简称DP(Dynamic Programming) 简介1 简介2 ...

随机推荐

  1. 【CodeForces】913 C. Party Lemonade

    [题目]C. Party Lemonade [题意]给定n个物品,第i个物品重量为2^(i-1)价值为ci,每个物品可以无限取,求取总重量>=L的最小代价.1<=30<=n,1< ...

  2. Vue 子路由 与 单页面多路由 的区别

    本文地址:http://www.cnblogs.com/veinyin/p/7911292.html 最近学完了基础课程,打算整理一波笔记,对基本概念梳理一遍,惊觉对子路由和单页面多路由混淆的一塌糊涂 ...

  3. qq上传文件进行测试要点分析

    功能 QQ 兼容性 1.Win系统/Mac系统  Android/IOS 品牌 传 1.上传方式:直接拖拽,按回车键上传 2.多个文件同时上传给一人/多人(考虑稳定性,是否存在内存泄露) 3.不是好友 ...

  4. Android :ExpandableListActivity

    http://developer.android.com/reference/android/app/ExpandableListActivity.html# public class Expanda ...

  5. 大数据系列之Hadoop框架

    Hadoop框架中,有很多优秀的工具,帮助我们解决工作中的问题. Hadoop的位置 从上图可以看出,越往右,实时性越高,越往上,涉及到算法等越多. 越往上,越往右就越火…… Hadoop框架中一些简 ...

  6. Codeforces Round #434 (Div. 2)

    Codeforces Round #434 (Div. 2) 刚好时间对得上,就去打了一场cf,发现自己的代码正确度有待提高. A. k-rounding 题目描述:给定两个整数\(n, k\),求一 ...

  7. 处理tomcat内存溢出问题

    TOMCAT起步内存溢出问题Exception in thread ""http-bio-8080"-exec-java.lang.OutOfMemoryError: P ...

  8. ActiveMQ-Prefetch机制和constantPendingMessageLimitStrategy

    首先简要介绍一下prefetch机制.ActiveMQ通过prefetch机制来提高性能,这意味这 客户端的内存里可能会缓存一定数量的消息.缓存消息的数量由prefetch limit来控 制.当某个 ...

  9. go当中寄生于变量的方法

    这个东东,好像其它语言很少见呢. 印象中,ruby是可以这样的. package main import ( "fmt" ) type user struct { name str ...

  10. 翻译:MLAPP(2.1节 概率概述)

    笔者:尝试翻译MLAPP(Machine Learning: a Probabilistic Perspective)一书,供机器学习的学者参考,如有错误理解之处请指出,不胜感激!(如需转载,请联系本 ...