首页 > 其他分享 >学习笔记:数论分块

学习笔记:数论分块

时间:2024-09-04 09:37:24浏览次数:4  
标签:lfloor right frac 分块 数论 sum 笔记 rfloor left

数论分块

1.0

可以快速计算一些含有除法向下取整的和式(形如 $\sum_{i=1}^n g(i) \left \lfloor \frac{n}{i}\right \rfloor $)。

2.0

引理1

\(\left \lfloor \frac{n}{i} \right \rfloor\) 的取值最多只有 \(2\times \sqrt n\) 种。

证明

对于 \(i \le \left \lfloor \sqrt n \right \rfloor\),显然有 \(\sqrt n\) 种取值。

对于 \(i > \sqrt n\),有 \(\left \lfloor \frac{n}{i} \right \rfloor \le \left \lfloor \sqrt n \right \rfloor\),有 \(\sqrt n\) 种取值。

2.1

引理2

使得 \(\left \lfloor \frac{n}{l} \right \rfloor = \left \lfloor \frac{n}{r} \right \rfloor\) 且满足 \(l \le r \le n\) 的 \(r\) 值最大为 \(\left \lfloor \frac{n}{\left \lfloor \frac{n}{l} \right \rfloor} \right \rfloor\)。

证明

令 \(k = \left \lfloor \frac{n}{i} \right \rfloor\),有 \(\left \lfloor \frac{n}{k} \right \rfloor \ge \left \lfloor \frac{n}{\frac{n}{i}} \right \rfloor = i\)。

$ \left \lfloor \frac{n}{\frac{n}{i}} \right \rfloor$ 为满足条件的最大值。

3.0

UVA11526

题意

多组数据,求 \(\sum_{i=1}^n \left \lfloor \frac{n}{i} \right\rfloor\)。

\(T\le1000 ,n\le 2^{31}-1\)。

解题

void Work() {
	ll n, res = 0;
	cin >> n;
	for(ll l = 1, r, k; l <= n; l = r+1) {
		k = n/l;
		r = n/k;
		res += k * (r-l+1);
	}
	cout << res << "\n";
}


P3935

题意

若 \(x\) 分解质因数结果为 \(x=p_1^{k_1}p_2^{k_2}\cdots p_n^{k_n}\),令\(f(x)=(k_1+1)(k_2+1)\cdots (k_n+1)\),求 \(\sum_{i=l}^rf(i)\) 对 \(998\,244\,353\) 取模的结果。

\(1\le l \le 10^{14}\),\(1\le r \le 1.6\times 10^{14}\),\(r-l>10^{14}\)。

解题

引理1

若 \(x\) 分解质因数结果为 \(x=p_1^{k_1}p_2^{k_2}\cdots p_n^{k_n}\),则 \(f(x)\) 为 \(x\) 的因数个数。

证明

对于 \(x\) 的一个因数 \(y\),将其必定能表示为 \(y=p_1^{a_1}p_2^{a_2}\cdots p_n^{a_n}\)。

且每个 \(a_i\) 有 \([0, k_i]\) 共 \(k_i+1\) 种取值。

故 \(x\) 的因数个数为 \((k_1+1)(k_2+1)\cdots (k_n+1)\)。

引理2

\(1\) 至 \(n\) 中,含有因子 \(d(1\le d\le n)\) 的数的个数为 \(\left \lfloor \frac{n}{d} \right \rfloor\)。

证明略。

所以题目要求的即是 \(\sum_{i=1}^r \left \lfloor \frac{r}{i} \right\rfloor - \sum_{i=1}^{l-1} \left \lfloor \frac{l-1}{i} \right\rfloor\)。套板子即可。


P2261

题意

求 \(\sum_{i=1}^nk \bmod i,1\le n,k \le 10^9\)。

解题

\(\sum_{i=1}^n k \bmod i = \sum_{i=1}^n k - \left \lfloor \frac{k}{i} \right \rfloor \times i = n \times k - \sum_{i=1}^n \left \lfloor \frac{k}{i} \right \rfloor \times i\)。

考虑怎么求出 \(\sum_{i=1}^n \left \lfloor \frac{k}{i} \right \rfloor \times i\)。

对于一段区间,其值一定,考虑求 \(\sum_{i=l}^r d\times i\),用等差数列求和公式即可,首项为 \(l\times d\),末项为 \(r\times d\),项数为 \(r-l+1\)。

code:


#include<iostream>
#include<cstdio>
#define F(i, l, r) for(int (i) = (l); (i) <= (n); (i) ++)
#define ll long long
using namespace std;
ll n, k;
int main() {
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	cin >> n >> k;
	ll res = 0;
	for(ll l = 1, r, d; l <= n; l = r+1) {
		d = k/l;
		if(!d) break;
		r = min(k/d, n);
      		//注意边界
		res += (r-l+1) * (l + r) * d / 2;
	}
	cout << n*k - res << "\n";
	return 0;
} 


P2260

题意

求 \(\sum_{i=1}^n \sum_{j=1}^m(n \bmod i) \times (m \bmod j), i \ne j\)。

\((1\le n,m\le10^9)\)。

解题

原式 \(= \sum_{i=1}^n(n \bmod i) \times \sum_{j=1}^m(m \bmod j) - \sum_{i=1}^{\min(n,m)}(n\bmod i)\times(m\bmod i)\)

\(= \sum_{i=1}^n(n-\left\lfloor \frac{n}{i} \right\rfloor\times i) \times \sum_{j=1}^m(m-\left\lfloor \frac{m}{i} \right\rfloor\times i) - \sum_{i=1}^{\min(n,m)}(n-\left\lfloor \frac{n}{i}\right\rfloor\times i)\times(m-\left\lfloor\frac{m}{i}\right\rfloor\times i)\)

前面部分同上题,考虑如何求最后一部分。

\(\sum_{i=1}^{\min(n,m)}(n-\left\lfloor \frac{n}{i}\right\rfloor\times i)\times(m-\left\lfloor\frac{m}{i}\right\rfloor\times i)\)

\(=\sum_{i=1}^{\min(m,n)}(nm-n\left\lfloor\frac{m}{i}\right\rfloor\times i - m\left\lfloor\frac{n}{i}\right\rfloor\times i+\left\lfloor\frac{n}{i}\right\rfloor \left\lfloor\frac{m}{i}\right\rfloor\times i^2)\)。

发现只有最后一项不好求,我们有:

\(\sum_{i=1}^n i^2 = \frac{n(n+1)(2n+1)}{6}\)

证明

\(\sum_{i=1}^n i^2 = \sum_{i=1}^ni(i-1)+i = \sum_{i=1}^n 2\times\binom{i}{2} +i\)

接着逆用帕斯卡公式:\(\binom{n}{k} = \binom{n-1}{k-1} + \binom{n-1}{k}\)。

\(2\times\sum_{i=1}^n \binom{i}{2} = 2\times \binom{n+1}{3} = \frac{n(n+1)(n-1)}{3}\)

代入原式,得

\(\sum_{i=1}^n i^2 = \sum_{i=1}^ni(i-1)+i = \sum_{i=1}^n \binom{i}{2} +i = \frac{n(n+1)(n-1)}{3} + \frac{n(n+1)}{2} = \frac{n(n+1)(2n+1)}{6}\)

code

#include<bits/stdc++.h>
#define F(i, l, r) for(int (i) = (l); (i) <= (n); (i) ++)
#define ll long long
#define i128 __int128
using namespace std;
const ll mo = 19940417;
ll calc(ll n) {
	ll res = n * n;
	for(ll l = 1, r, d; l <= n; l = r+1) {
		d = n/l;
		r = n/d;
		res -= d * (l+r) * (r-l+1) / 2;
	}
	return res % mo;
}
ll funa(ll l, ll r) {
	return ((i128)(l+r) * (r-l+1) / 2 % mo);
}
ll func(ll x) {
	return ((i128)x * (x+1) * (2*x+1) / 6 % mo);
}
ll funb(ll l, ll r) {
	return ((func(r) - func(l-1)) % mo + mo) % mo;
}
int main() {
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	ll n, m;
	cin >> n >> m;
	ll a = calc(n), b = calc(m);
	ll w = min(n, m);
	ll c = n * m % mo * w % mo;
	for(ll l = 1, r, d; l <= w; l = r+1) {
		ll num1 = n/l, num2 = m/l;
		r = min(n/num1, m/num2);
		c = ((c - 
		funa(l, r) * ((m*num1 + n*num2) % mo)%mo
		+ (funb(l, r) * num1 % mo * num2 % mo )%mo) %mo + mo)%mo;
	}
	cout << ((a * b % mo - c) % mo + mo) % mo;
	return 0;
} 


P3636

题意

求在三维坐标系中所有满足 \(a\le x\times y\times z \le b\) 的点 \((x,y,z)\) 到原点的曼哈顿距离的平方和。

数据范围:\(1\le a,b\le 3\times 10^8\)。

解题

为了方便我们将 \(x,y,z\) 三个数均限制在正整数范围内,三个数乘积为正有两负一正和全正共 \(\binom{3}{2} + 1 = 4\) 种情况,所以最终答案乘 \(4\) 即可。

容易想到将询问进行差分,所以我们考虑求 \(\sum_{i=1}^{n}\sum_{j=1}^{\left\lfloor\frac{n}{i}\right\rfloor}\sum_{k=1}^{\left\lfloor\frac{n}{i\times j}\right\rfloor}(i+j+k)^2\) 即可。

$ \begin{aligned}\sum_{i=1}{n}\sum_{j=1}\right\rfloor}\sum_{k=1}^{\left\lfloor\frac{n}{i\times j}\right\rfloor}(i+j+k)^2 &=\sum_{i=1}{n}\sum_{j=1}\right\rfloor}\sum_{k=1}^{\left\lfloor\frac{n}{i\times j}\right\rfloor}i^2 + (j+k)^2 + 2ij + 2ik \&= \sum_{i=1}n(i2\sum_{j=1}^{\left\lfloor\frac{n}{i}\right\rfloor}\left\lfloor\frac{n}{i\times j}\right\rfloor + 2i\sum_{j=1}{\left\lfloor\frac{n}{i}\right\rfloor}\sum_{k=1}\right\rfloor}(j+k)+\sum_{j=1}{\left\lfloor\frac{n}{i}\right\rfloor}\sum_{k=1}\right\rfloor}(j+k)^2)\end{aligned}$

容易发现 \(\sum_{j=1}^{\left\lfloor\frac{n}{i}\right\rfloor}\left\lfloor\frac{n}{i\times j}\right\rfloor,\sum_{j=1}^{\left\lfloor\frac{n}{i}\right\rfloor}\sum_{k=1}^{\left\lfloor\frac{n}{i\times j}\right\rfloor}(j+k),\sum_{j=1}^{\left\lfloor\frac{n}{i}\right\rfloor}\sum_{k=1}^{\left\lfloor\frac{n}{i\times j}\right\rfloor}\) 这三部分用数论分块都是好维护的。

所以我们数论分块套数论分块维护即可。

由于时间限制,应尽量减少取模次数。

code:

#include<iostream>
#include<cstdio>
#define ll long long

using namespace std;
const ll mo = 10007;
ll inv2, inv6;
struct node{
	ll ans1, ans2, ans3;
};
ll Pow(ll a, ll b) {
	ll res = 1;
	for(; b; b>>=1) {
		if(b&1) res = res * a % mo;
		a = a * a % mo;
	}
	return res;
}
inline ll funa(ll l, ll r) {
	return (l+r) * (r-l+1) %mo * inv2 %mo;
}
inline ll ready(ll x) {
	return x * (x+1) % mo * (2*x+1) % mo * inv6 % mo;
}
inline ll funb(ll l, ll r) {
	return ((ready(r) - ready(l-1)) % mo + mo)% mo;
}
node work2(ll n) {
	ll ans1 = 0, ans2 = 0, ans3 = 0;
	for(ll l = 1, r, d; l <= n; l = r+1) {
		d = n/l;
		r = n/d;
		ans1 = (ans1 + (r-l+1) * d ) % mo;
		ans2 = (ans2 + funa(l, r) * d + (r-l+1) * funa(1, d)) % mo;
		ans3 = (ans3 + funb(l, r) * d + (r-l+1) * funb(1, d) + 2 * funa(l, r) * funa(1, d)) % mo;
	}
	node u;
	u.ans1 = ans1;
	u.ans2 = ans2;
	u.ans3 = ans3;
	return u;
}
ll work(ll n) {
	ll ans = 0;
	for(ll l = 1, r, d; l <= n; l = r+1) {
		d = n/l;
		r = n/d;
		node u = work2(d);
		ll ans1 = u.ans1, ans2 = u.ans2, ans3 = u.ans3;
		ans = (ans + funb(l, r)*ans1 + funa(l, r)*2ll*ans2 + (r-l+1)*ans3) % mo;
	}
	return ans;
}
int main() {
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	ll a, b;
	cin >> a >> b;
	inv2 = Pow(2, mo-2);
	inv6 = Pow(6, mo-2);
	cout << (work(b) - work(a-1) + mo) * 4ll%mo;
	return 0;
}

参考资料:

https://www.cnblogs.com/rickylin/p/17790471.html

https://oi-wiki.org/math/number-theory/sqrt-decomposition/

https://www.cnblogs.com/mangoworld/p/Number-Theory-Block.html

https://www.luogu.com/article/jcsvb4vh

标签:lfloor,right,frac,分块,数论,sum,笔记,rfloor,left
From: https://www.cnblogs.com/SLDS/p/18395851

相关文章

  • 【深度学习】嘿马深度学习笔记第7篇:卷积神经网络,学习目标【附代码文档】
    本教程的知识点为:深度学习介绍1.1深度学习与机器学习的区别TensorFlow介绍2.4张量2.4.1张量(Tensor)2.4.1.1张量的类型TensorFlow介绍1.2神经网络基础1.2.1Logistic回归1.2.1.1Logistic回归TensorFlow介绍总结每日作业神经网络与tf.keras1.3神经网络基础......
  • 【Python学习笔记】第1章 问答环节
    人们为什么使用Python软件质量:可读性、可维护性开发者生产效率:代码更少程序的可移植性:同样的代码在不同的操作系统中都可以运行标准库的支持:内置可移植的功能模块组件构成:轻松地与应用程序的其他部分通信享受乐趣:略软件质量追求代码简洁,可读性模块化、面向......
  • 第二天学习笔记:Datawhale X 李宏毅苹果书 AI夏令营
    今天学的有些小兴奋,终于解锁了很多熟悉但不明就里的术语。天呢,原来ReLU是“修正线性单元”的意思!RectifiedLinearUnit!但是呢,也有不大对付的地方:好几个地方前言不搭后语。容我一一道来。今天就顺序边读边记:线性模型(linearmodel)==把模型输入的特征x乘上一个权重,再加......
  • mini-lsm通关笔记Week1Day7
    Summary在上一章中,您已经构建了一个具有get/scan/put支持的存储引擎。在本周末,我们将实现SST存储格式的一些简单但重要的优化。欢迎来到Mini-LSM的第1周零食时间!在本章中,您将:在SST上实现布隆过滤器,并集成到LSM读路径get中。以SST块格式实现对key存储的压缩。要将测试用例......
  • Mybatis学习笔记
    本笔记基于【尚硅谷新版SSM框架全套视频教程,Spring6+SpringBoot3最新SSM企业级开发】https://www.bilibili.com/video/BV1AP411s7D7?vd_source=a91dafe0f846ad7bd19625e392cf76d8总结资料获取网址:https://www.wolai.com/v5Kuct5ZtPeVBk4NBUGBWFMyBatis实践:提高持久层数据......
  • CMake构建学习笔记14-依赖库管理工具
    如果说做C/C++开发最大的痛点是什么,那么一定是缺少一个官方的统一的包管理器。认真的说,如果你要用C/C++干点什么,至少需要(Windows系统下):C/C++语言本身、标准库、以及操作系统API几乎干不了什么,除非你真的想从零开始造轮子。开始找一些现成的实现组成依赖库。最好看能不能找到预......
  • 【读书笔记-《30天自制操作系统》-14】Day15
    本篇内容开始讲解多任务。本篇内容结构很简单,先讲解任务切换的原理,再讲解任务切换的代码实践。但是涉及到的知识不少,理解上也有些难度。1.任务切换与多任务原理1.1多任务与任务切换所谓多任务,指的是操作系统同时运行多个任务。但是这种说法实际上是不准确的。如果只有......
  • 手动脱壳学习笔记1----手动脱upx壳
    ESP定律脱壳例题https://files.buuoj.cn/files/ee7f29503c7140ae31d8aafc1a7ba03f/attachment.tar两下F9按一下F9,ESP变红在ESP处右键在内存窗口处转到在下面的内存下硬件断点再按一下F9在401280处下断点scylla插件输入00401820最后处理......
  • 并发编程学习笔记1
    1.线程的创建    方法一:直接重写Thread类的run方法Threadt=newThread(){@Overridepublicvoidrun(){}};t.start();    可简写为:Threadt3=newThread(()->{});t.start();    方法二:使用Runnable配合ThreadRunna......
  • 2-SAT 学习笔记
    一、简介k-SAT(satisfiability)解决这样一类问题:给定\(n\)个布尔变量和\(m\)条限制,每条限制形如\(x_1=0/1\or\cdots\orx_n=0/1\),求是否有解并给出构造。当\(k\gt2\)时,该问题为NP完全问题。二、算法流程在学习本算法前,请确保你对有向图强连通分量有一定了解。例......