当前位置: 首页 > news >正文

Min_25筛

Min_25筛是一种优秀的求积性函数前缀和的方法, 时间复杂度\(O\left(\frac{n^{\frac{3}{4}}}{\log}\right)\), 空间复杂度\(O(\sqrt{n})\).

记号

\(p\)一般表示一个质数, \(\lim=\sqrt{n}\), \(P\) 表示 $\le \lim $ 质数集, 其中 \(P_i\) 表示第 \(i\) 大的质数.

条件

\(f(p)\)是一个低次多项式;

\(f(p^x )\)可以快速计算;

对于一个多项式, 我们将每一项拆开, 分别做min_25筛. 要满足每一项是积性函数.

质数部分

(以下关于合数的函数计算就假装它是质数, 把函数当成完全积性函数,方便计算, 反正我们只要质数部分的答案QAQ)

\(g(n,j)\)表示, 在小于等于\(n\)的数\(i\)中, 满足本身是质数或者最小质因子大于\(P_j\)的所有\(f(i)\)之和.

特别的, \(g(n,0)\)表示\(x=2\dots n\)\(f(x)\)和.

(其实就是筛质数时筛完第\(i\)个质数后剩下的没有被筛掉的数)

递推\(g(n,j)\):
考虑从\(g(n,j-1)\)转移过来. \(g(n,j-1)\)\(g(n,j)\)多算的部分其实就是最小质因子为\(P_j\)的合数.
\[ \small{ g(n,j)= \begin{cases} g(n,j-1)&, P_j^2>n \\ g(n,j-1) - f(P_j)\left[g\left(\lfloor\frac{n}{P_j}\rfloor,j-1\right) -g(P_j-1,j-1) \right] &, Otherwise \end{cases} } \]
(上面的\(f(P_j)\)可以直接乘后面的部分是因为上面提到的我们是当做完全积性函数计算的)
边界\(g(n,0)\)即为自然数幂和.
可以直接递归求, 也可以求出所有的\(\lfloor \frac{n}{i}\rfloor\), 直接离散后存在一维数组中(由于只会转移到更大的数, 所以一维就够了); 对于\(g(P_j-1,j-1)\), 即小于\(P_j\)的所有质数的函数值, 可以直接预处理.

如果要求所有质数的函数值, 那么答案就是\(g(n,\lim)\).(因为\(g(n,j)\)的定义是关于最小质因子, 一个合数的最小质因子一定不大于\(\sqrt{n}\))

合数部分

\(S(n,j)\)表示\(n\)以内的所有数中最小质因子大于等于\(P_j\)的所有数的函数值之和.

那么有转移:
\[ \small{ S(n,j) = g(n, \lim) - g(P_j - 1, j - 1) + \sum_{k=j+1}^{P_k^2 \le n}\sum_{e = 1}^{P_k^{e+1} \le n} f(P_k^{e}) S\left(\lfloor\frac{n}{P_k^{e}}\rfloor,k+1\right) + f(p_k^{e+1}) } \]
\(S(n,j)\)中的质数部分即\(g(n,j-1)\)除掉小于\(P_j\)的质数的函数值, 这里的\(g(P_j - 1, j-1)\)和上面一样是可以预处理的.

对于合数部分, 我们枚举它的最小质因子\(P_k\)以及它的次数\(e\)递归到下一层, 但是这样会少算\(f(P_k^e)\)的贡献, 加上就是了.

\(S(n,1)+f(1)\)即为答案.

例题

SPOJ DIVCNTK

Description

\[S_k(n) = \sum_{i=1}^n \sigma_0(i^k)\]
\(2^{64}\)取模, \(n\le 10^{10}\).

Solution

\(f(x) = \sigma_0(x^k)\), 那么有:

\(f(p^e) = ke + 1\)\(f(x)\)为积性函数, 直接Min_25筛即可.

Code

const int MAXS = 1e6 + 5;

LL n;
ULL K;
int s;

int pr[MAXS], prs;
void sieve(int n) {
    static int np[MAXS];
    For(i, 2, n) {
        if (!np[i]) pr[++ prs] = i;
        for (int j = 1; j <= prs && pr[j] * i <= n; ++ j) {
            np[i * pr[j]] = 1;
            if (i % pr[j] == 0) break;
        }
    }
}

int lss, id1[MAXS], id2[MAXS];
LL ls[MAXS << 1];
ULL g[MAXS << 1];
#define id(x) ((x) <= s ? id1[x] : id2[n / (x)])
void calc_g() {
    lss = 0;
    for (LL l = 1, r = 0; r < n; l = r + 1) {
        r = n / (ls[++ lss] = n / l);
        g[lss] = ls[lss] - 1, id(ls[lss]) = lss;
    }
    For(i, 1, prs) {
        LL bot = (LL)pr[i] * pr[i];
        if (bot > n) break;
        for (int j = 1; j <= lss && bot <= ls[j]; ++ j)
            g[j] -= g[id(ls[j] / pr[i])] - (i - 1);
    }
}

ULL S(LL m, int j) {
    if (m <= 1 || pr[j] > m) return 0;
    ULL ans = (g[id(m)] - (j - 1)) * (K + 1);
    for (int k = j; k <= prs && (LL)pr[k] * pr[k] <= m; ++ k)
        for (LL prod = pr[k], e = 1; prod * pr[k] <= m; prod *= pr[k], ++ e)
            ans += S(m / prod, k + 1) * (K * e + 1) + (K * (e + 1) + 1);
    return ans;
}

int main() {
#ifdef hany01
    freopen("DIVCNTK.in", "r", stdin);
    freopen("DIVCNTK.out", "w", stdout);
#endif

    sieve(1e6);

    for (int T = read<int>(); T --; ) {
        s = sqrt(n = read<LL>()), K = read<ULL>();
        calc_g(), printf("%llu\n", S(n, 1) + 1);
    }

    return 0;
}

一些技巧与启发

1.对于质数部分, Min_25筛每次将合数的最小质因子筛去. 我们可以利用这个性质处理一些有关最小质因子的问题.
2.对于合数部分, 我们每次从小到大枚举质因子, 我们可以对于枚举的质因子加上一些约束(注意同时修改质数部分), 也可以对最大质因子,次大质因子进行计算.(UOJ188)
3.筛数时可以考虑每个数的最小质因子, 因为合数的最小质因子是\(\le \sqrt{n}\)的.

转载于:https://www.cnblogs.com/Hany01/p/min25-sieve.html

相关文章:

  • spring-boot切面编程-日志记录
  • 从0到1学C++ 第2篇 认识C++面向过程编程的特点
  • Java01
  • 苹果下调财收预期,致使股价大跌近10%,万亿身家缩水近一半
  • 图像的等距变换,相似变换,仿射变换,射影变换
  • 解决NoclassDefFoundError 打印一个类的java路径
  • 从Lucene到Elasticsearch:从 Lucene 到 ElasticSearch
  • 【文文殿下】ExBSGS
  • [HNOI2008]Cards
  • Facebook 2018 年度开源回顾:新增开源项目 153 个
  • 游戏开发中的抛物线(贝塞尔曲线)
  • Vue UI框架库开发介绍
  • MultipartFile 不能直接 转成File对象
  • react native 包学不包会系列--react native开发基础知识
  • 老鼠的商议
  • JS 中的深拷贝与浅拷贝
  • Electron入门介绍
  • es6
  • ES6系列(二)变量的解构赋值
  • Java编程基础24——递归练习
  • js正则,这点儿就够用了
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • Spring Security中异常上抛机制及对于转型处理的一些感悟
  • 浮动相关
  • 记一次和乔布斯合作最难忘的经历
  • 我这样减少了26.5M Java内存!
  • 在Docker Swarm上部署Apache Storm:第1部分
  • 正则表达式
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • ​LeetCode解法汇总518. 零钱兑换 II
  • ​猴子吃桃问题:每天都吃了前一天剩下的一半多一个。
  • (二)windows配置JDK环境
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (附源码)ssm高校运动会管理系统 毕业设计 020419
  • (附源码)ssm高校志愿者服务系统 毕业设计 011648
  • (原創) 如何優化ThinkPad X61開機速度? (NB) (ThinkPad) (X61) (OS) (Windows)
  • (转)原始图像数据和PDF中的图像数据
  • (轉貼) 資訊相關科系畢業的學生,未來會是什麼樣子?(Misc)
  • * 论文笔记 【Wide Deep Learning for Recommender Systems】
  • ***测试-HTTP方法
  • .helper勒索病毒的最新威胁:如何恢复您的数据?
  • .NET CORE 第一节 创建基本的 asp.net core
  • @TableLogic注解说明,以及对增删改查的影响
  • @transactional 方法执行完再commit_当@Transactional遇到@CacheEvict,你的代码是不是有bug!...
  • [ vulhub漏洞复现篇 ] Jetty WEB-INF 文件读取复现CVE-2021-34429
  • []AT 指令 收发短信和GPRS上网 SIM508/548
  • [2021ICPC济南 L] Strange Series (Bell 数 多项式exp)
  • [Angular 基础] - 数据绑定(databinding)
  • [APIO2015]巴厘岛的雕塑
  • [C语言]——柔性数组
  • [Django ]Django 的数据库操作
  • [GDOUCTF 2023]<ez_ze> SSTI 过滤数字 大括号{等
  • [HTTP]HTTP协议的状态码
  • [javaSE] GUI(Action事件)
  • [LeetCode]-225. 用队列实现栈