首页 > 其他分享 >数论分块

数论分块

时间:2023-07-11 20:57:53浏览次数:27  
标签:lfloor 分块 数论 dfrac sum rfloor ll

概念

我们考虑这样一个问题:求 \(\sum_{i=1}^{k} \lfloor \dfrac{n}{i} \rfloor\)

我们以 \(n=7,k=7\) 为例子,先画出 \(f(x) = \dfrac{7}{x} \ (1 \leq x \leq 7)\) 的图像

因为我们的取值是向下取整的,我们描出所有可能的取值

注意到所有的点按照取值可以分成若干段

我们可以一次性处理一个段的答案,把整段对答案的贡献加上即可

这就是数论分块

实现

如果要实现整块一起统计,我们需要求出每一块的块头 \(l\) 和块尾 \(r\),则:

\[Ans = \sum_{i=1}^{k} \lfloor \dfrac{n}{i} \rfloor = \sum_{[l,r]} (r-l+1)(\lfloor \dfrac{n}{l} \rfloor) \]

注意到每一块的 \(l\) 都可以由上一块的 \(r\) 推出,故我们继续讨论如何在已知 \(l\) 的情况下推出 \(r\)

令 \(t = \lfloor \dfrac{n}{l} \rfloor\) ,容易得到

\[\begin{cases} r = \min(\lfloor \dfrac{n}{t} \rfloor,n) \ \ \ &(t \neq 0) \\ r = n \ \ \ &(t=0) \end{cases} \]

直接计算即可

应用

P2261 [CQOI2007]余数求和

先推式子

\[\begin{aligned} G(n,k) &= \sum_{i=1}^{n} k \bmod i \\ &= \sum_{i=1}^{n} k - i \times \lfloor \dfrac{k}{i} \rfloor \\ &= nk - \sum_{i=1}^{n} i \times \lfloor \dfrac{k}{i} \rfloor \end{aligned} \]

直接用数论分块解决即可

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;

ll n, k, res;

signed main() {
    scanf("%lld%lld", &n, &k);

    for (ll l = 1, r; l <= n; l = r + 1) {
        r = (k / l) ? min(k / (k / l), n) : n;
        res += (k / l) * ((l + r) * (r - l + 1) >> 1);
    }

    printf("%lld", n * k -res);
    return 0;
}

P3935 Calculating

令 \(g(x) = \sum_{i=1}^{n} f(i)\) ,则

\[\sum_{i=l}^{r} = g(r) - g(l-1) \]

我们推一下 \(g(x)\)

\[\begin{aligned} g(x) &= \sum_{i=1}^{x} f(i) \\ &= \sum_{i=1}^{x} \sum_{j=1}^{x} [i \mid j] \\ &= \sum_{i=1}^{x} \lfloor \dfrac{x}{i} \rfloor \end{aligned} \]

直接用数论分块解决即可

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll Mod=998244353;

ll l, r;

inline ll g(ll n) {
	ll res = 0;
	
	for (ll l = 1, r; l <= n; l = r + 1) {
	    r = (n / l) ? min(n / (n / l), n) : n;
	    res = (res + (n / l) * (r - l + 1)) % Mod;
	}
	
	return res;
}

signed main() {
	scanf("%lld%lld", &l, &r);
	printf("%lld", ((g(r) - g(l - 1)) % Mod + Mod) % Mod);
	return 0;
}

标签:lfloor,分块,数论,dfrac,sum,rfloor,ll
From: https://www.cnblogs.com/wshcl/p/17545884.html

相关文章

  • 测试大文件分块和合并
    文件分块的流程获取源文件长度根据设定的分块文件大小,计算出块数(向上取整,例如33.4M的文件,块大小为1M,则需要34块)从源文件读取数据,并依次向每一个块文件写数据文件分块测试代码如下/***分块测试*/@TestvoidtestChunk()throwsIOException{//源......
  • 20230710-20230711 数论
    数论被薄纱了/kk授课老师:南京大学-朱富海教授20230710裴蜀定理对于给定不全为零的整数的\(a,b\)一定存在一对整数\(x,y\)满足\(ax+by=gcd(a,b)\)。证明:\(a==0\)\(or\)\(b==0\)显然成立;设\(gcd(a,b)=d\),即求证存在\(x,y\)满足\(ax+by=d\),等式两边同时除......
  • 数论专题练习
    数论专题练习A-BeautifulNumbers题意:输入a,b,n,求只包含a,b的n位数并且n位之和为a或b的数量枚举a和b的数量,判断它们的和是否为一个good_number,然后用组合数(详见数论的组合数)求和#include<bits/stdc++.h>usingnamespacestd;constintp=1e9+7;constintMAXN=1e6......
  • 整除分块(数论分块)
    整除分块是为了解决一个整除的求和的问题:sum(floor(n/i))(1<=i<=n) ,如果直接暴力计算复杂度O(n),但整除分块的复杂度为O(2sqrt(n)),其中的2为常数,可以忽略,那么复杂度为O(sqrt(n))下面给出整除分块的模板代码#include<bits/stdc++.h>#definelllonglongusingnamespacestd;ll......
  • 数论
    算法记号\(a\modp\):\(a\)除\(p\)的余数,等于\(a-p\times\lfloor\frac{a}{p}\rfloor\)。\(a\midb\):\(a\)整除\(b\)即\(a\)是\(b\)的因数。素数判定试除法对于任意整数\(n\),它的因数\(d,\frac{n}{d}\)总是成对出现,所以可以枚举\([2,\sqrt{n}]\)内的数......
  • 「学习笔记」数列分块入门 1 ~ 9
    一天多一点的时间,做完了这\(9\)道题,除了最后一道题之外,都感觉良好.这里是黄学长的博客.数列分块入门1区间加法,单点查值.很入门的题目了.暴力处理两边不完整的块,完整的块维护一个tag加法标记./*Thecodewaswrittenbyyifan,andyifanisneutral!!!......
  • 数论基础
    数论基础导读:快速幂取模、欧式筛法、裴蜀定理(贝祖定理)、威尔逊定理、费马定理、(扩展)中国剩余定理。快速幂取模求\(a^b\%p\)我们有时间复杂度\(O(b)\)的办法。但数据规模放大时,我们的显示界面难免会出现一个老熟人TLE,我们需要更快的方法。根据初中数学,\(a^b\)可以化为\((a^2......
  • 数列分块入门
    1.数列分块入门1区间修改,单点查询点击查看代码#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;constintMAXN=5e4+5;intn,len,cnt;inta[MAXN],tag[MAXN];intpos[MAXN],l[MAXN],r[MAXN];inlinevoidadd(intx,inty,intk){if(x>y)retu......
  • 快速数论变换NTT学习笔记
    前言在这篇文章中我介绍了什么是\(\text{FFT}\),但是在文中我们也说了一嘴这玩意是有精度误差的,三角函数和复数导致我们不得不进行取整操作。只要毒瘤出题人原因,那就可以\(\text{HackFFT}\)。Tips:根据《NOI大纲》的内容,卡精度和卡常数通常是不允许的。所以\(\text{FFT}......
  • [数论]数论函数/莫比乌斯反演
    数论函数/莫比乌斯反演1.1积性函数数论函数:可以认为是定义在整数上的函数。1)积性函数定义(a,b)=1,f(a,b)=f(a)f(b)2)积性函数性质对于积性函数\(f\),是被所有\(p^e\)处的值决定的a=1,f(b)=f(1)f(b)​ \(f(60)=f(4)\timesf(15)=f(4)\timesf(3)\timesf(5......