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

【数论分块】数论分块算法模板及真题

1.数论分块的含义

数论分块算法,就是枚举出使得取整函数发生变化的地方。
例如,对表达式 ⌊ n i ⌋ \lfloor \frac{n}{i} \rfloor in使用数论分块算法,就可以在 O ( n ) O(\sqrt n) O(n )的时间复杂度下枚举所有满足 ⌊ n i − 1 ⌋ + 1 = ⌊ n i ⌋ \lfloor \frac{n}{i-1}\rfloor+1 = \lfloor \frac{n}{i} \rfloor i1n+1=in的 i 。

2.算法模板

long long r;
for(int l = 1; l <= n; l = r + 1)
{r = k/(k/l)/*your code*/
}

变量 l 就是取整函数发生变化的位置,即满足 ⌊ n l − 1 ⌋ + 1 = ⌊ n l ⌋ \lfloor \frac{n}{l-1}\rfloor+1 = \lfloor \frac{n}{l} \rfloor l1n+1=ln(l = 1除外)的位置,变量 r 就是满足 ⌊ n x ⌋ = ⌊ n l ⌋ \lfloor \frac{n}{x}\rfloor = \lfloor \frac{n}{l} \rfloor xn=ln的所有x 中最大的一个。
直观上,该过程时间复杂度小于 O ( n ) O(n) O(n),因为每次往后跳的长度大于1,
该算法的实际复杂度为 O ( n ) O(\sqrt n) O(n )
正确性证明和时间复杂度证明,详见此处。写题不需要证明。

3.算法的优化点

将所有 ⌊ n i ⌋ \lfloor \frac{n}{i} \rfloor in结果一样的 i 一并取出,使得时间复杂度降为 O ( n ) O(\sqrt n) O(n )
涉及取整的地方均可能用到此算法,包括但不限于,整除(练习题1)、最大公因数(练习题3)、最小公倍数(练习题2)、取模(本文例题)。

4.例题

P2261 [CQOI2007] 余数求和

题目描述

给出正整数 n n n k k k,请计算

G ( n , k ) = ∑ i = 1 n k m o d i G(n, k) = \sum_{i = 1}^n k \bmod i G(n,k)=i=1nkmodi

其中 k m o d i k\bmod i kmodi 表示 k k k 除以 i i i 的余数。

输入格式

输入只有一行两个整数,分别表示 n n n k k k

输出格式

输出一行一个整数表示答案。

输入输出样例 #1

输入 #1

10 5

输出 #1

29

说明/提示

样例 1 解释

G ( 10 , 5 ) = 0 + 1 + 2 + 1 + 0 + 5 + 5 + 5 + 5 + 5 = 29 G(10, 5)=0+1+2+1+0+5+5+5+5+5=29 G(10,5)=0+1+2+1+0+5+5+5+5+5=29

数据规模与约定
  • 对于 30 % 30\% 30% 的数据,保证 n , k ≤ 1 0 3 n , k \leq 10^3 n,k103
  • 对于 60 % 60\% 60% 的数据,保证 n , k ≤ 1 0 6 n, k \leq 10^6 n,k106
  • 对于 100 % 100\% 100% 的数据,保证 1 ≤ n , k ≤ 1 0 9 1 \leq n, k \leq 10^9 1n,k109

解题思路

  • a % b = a − ⌊ a b ⌋ ∗ b a \% b =a- \left \lfloor \frac{a}{b} \right \rfloor *b a%b=abab
  • 求和时,前半部分和后半部分,分开处理。
  • 数列 a i = i ∗ ⌊ x i ⌋ a_i =i * \left \lfloor \frac{x}{i} \right \rfloor ai=iix,在 ⌊ x i ⌋ \left \lfloor \frac{x}{i} \right \rfloor ix为不变值的时候,是等差数列。

AC代码

#include<bits/stdc++.h>
#define int long longusing namespace std;
typedef pair<int,int> PII;
const int mod = 998244353;
void solve()
{int n,k;cin >> n >> k;long long ans = 0;ans += n*k;int r;for(int i = 1; i <= n; i = r + 1){if(k/i == 0) break;r = min(k/(k/i),n);ans -= (r-i+1)*(i+r)/2 *(k/i);}cout << ans << '\n';
}signed main()
{ios::sync_with_stdio(false);cin.tie(0);int t = 1;//cin >> t;while(t --){solve();}
}

练习题

  • 【AtCoder Regular Contest 150B】
  • 【2025CCPC北京市赛】
  • 【2021ICPC陕西省赛】
http://www.xdnf.cn/news/155611.html

相关文章:

  • # 家庭网络IPv6地址的一些知识
  • 思科路由器重分发(静态路由+OSPF动态路由+RIP动态路由)
  • 基于MTF的1D-2D-CNN-BiLSTM-Attention时序图像多模态融合的故障分类识别(Matlab完整源码和数据),适合研究学习,附模型研究报告
  • Leetcode刷题 由浅入深之哈希法——454. 四数相加Ⅱ
  • Logi Options+ 的 Flow:端口信息
  • 驱动开发(1)|鲁班猫rk356x内核编译,及helloworld驱动程序编译
  • 微信小程序核心技术栈
  • ORACLE数据库备份入门:第四部分:2-备份场景举例
  • 计算机视觉——对比YOLOv12、YOLOv11、和基于Darknet的YOLOv7的微调对比
  • MyBatis 官方子项目详细说明及表格总结
  • JavaScript基础知识合集笔记1——数据类型
  • TDengine 中的压缩设计
  • 毕业项目-Web入侵检测系统
  • 关于TCP三次握手和四次挥手的疑点
  • 游戏状态管理:用Pygame实现场景切换与暂停功能
  • Unity-Shader详解-其一
  • MySQL多查询条件下深度分页性能优化技巧及示例总结
  • Pytorch(无CPU搭建)+Jupyter
  • Unity-Shader详解-其二
  • 【WLAN】华为无线AC双机热备负载分担—双链路热备份
  • 【数据融合】基于拓展卡尔曼滤波实现雷达与红外的异步融合附matlab代码
  • C++异步并发支持库future
  • 探针台的具体分类有哪些
  • 基于pandoc的MarkDown格式与word相互转换小工具开发(pyqt5)
  • AAAI2016论文 UCO: A Unified Cybersecurity Ontology
  • Eclipse 插件开发 1
  • MEME在线进行蛋白氨基酸序列的保守基序预测的具体分析步骤
  • 【Tauri】桌面程序exe开发 - Tauri+Vue开发Windows应用 - 比Electron更轻量!8MB!
  • 提取PPT图片
  • 数据库监控功能-oracle