牛客 | 小G的约数引起的对于 整数分块 学习
整除分块是个啥:要求
假设 n = 20
,然后打表
i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
20/i | 20 | 10 | 6 | 5 | 4 | 3 | 2 | 2 | 2 | 2 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
看到这个表不难发现规律,用20再去除以 (20/i) 就等于最后一个等于这个值的数,比如说 当i=7时,20/i=2,那么用20/(20/7) = 10, 这个时候10就是20/i等于2的最后一个值。可以利用这个特性,在区间最左边用O(1)的时间就可以计算出区间最右边的坐标。在这个区间内,所有的值都是相同的,所以找到这个区间后,直接用区间长度乘以单个数值就ok。
// Core Code
ll G(ll n) {
ll cnt = 0;
for (int l = 1, r; l <= n; l = r + 1) {
r = n / (n / l); // 区间最右边
cnt += (n / l) * (r - l + 1);
}
return cnt;
}
Next:余数求和 要求
在每一段(L,R)中 k/i = k/L ,所以在相加的时候可以当作公因式提出来。
所以每一段(L,R)的和可以表示为 k/L * (R-L+1) * (L+R) / 2。
// RioTian 21/03/03
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll n, k, cnt;
int main() {
cin >> n >> k;
cnt = n * k;
for (ll l = 1, r; l <= n; l = r + 1) {
if (k / l != 0)
r = min(n, k / (k / l));
else
r = n;
cnt -= (k / l) * (r - l + 1) * (l + r) / 2;
}
cout << cnt << "\n";
return 0;
}
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· 分享4款.NET开源、免费、实用的商城系统
· 解决跨域问题的这6种方案,真香!
· 一套基于 Material Design 规范实现的 Blazor 和 Razor 通用组件库
· 5. Nginx 负载均衡配置案例(附有详细截图说明++)
2020-03-03 LeetCode 题解 | 70. 爬楼梯
2020-03-03 LeetCode 题解 | 242. 有效的字母异位词
2020-03-03 LeetCode 题解 | 面试题 10.01. 合并排序的数组
2020-03-03 PTA | 03-树2 List Leaves (25分)
2020-03-03 PTA | 03-树1 树的同构 (25分)