首页 > 其他分享 >整除分块

整除分块

时间:2024-02-01 09:36:36浏览次数:25  
标签:分块 cdot dfrac sum sqrt 枚举 整除 ll

常搭配莫反食用。莫比乌斯反演笔记

P2261 余数求和

求 \(\displaystyle\sum_{i=1}^n k\bmod i\),\(n,k\le 1e9\)。

第一步:\(k\bmod i=k-i\cdot\lfloor\dfrac{k}{i}\rfloor\),\(\text{原式}=\displaystyle\sum_{i=1}^nk-i\cdot[\frac{k}{i}]\).

第二步:\(\text{原式}=nk-\displaystyle\sum_{i=1}^ni\cdot[\dfrac{k}{i}]\)。

然后问题就是怎么求 \(\sum_{i=1}^ni\cdot [\dfrac{k}{i}]\) 了。

直接枚举肯定是不行的,但是 \([\dfrac{k}{i}]\) 只有 \(\sqrt k\) 种取值!

所以可以枚举 \([\dfrac{k}{i}]\) 的值。当这个值确定了,求出 \([\dfrac{k}{i}]\) 等于这个值的区间,然后在这个区间内就很简单了

因为取值只有 \(\sqrt k\) 种,所以区间只有 \(\sqrt k\) 个。我们每个区间 \(O(1)\),总复杂度就是 \(O(\sqrt k)\)。

怎么实现枚举取值?直接枚举又变成 \(O(k)\) 了,不行。

我们可以用类似双指针的方法,初始让指针 \(l=1\),求出 \([\dfrac{k}{i}]\) 等于 \([\dfrac{k}{l}]\) 的最大的 \(i\),令指针 \(r\leftarrow i\)。算完这段区间再令 \(l\leftarrow r+1\),不断循环,直到 \(l\) 超过 \(n\)。

一定要搞清楚 \(l\) 的上界,还有 \(r\) 是根据什么确定的!

怎么求 \(r\)?令 \(p=[\dfrac{k}{l}]\),\(l\) 已知,这是可以 \(O(1)\) 求出的。我们求出 \([\dfrac{k}{i}]=p\) 中 \(i\) 的范围,最大的 \(i\) 就是 \(r\) 。

\([\dfrac{k}{i}]=p\iff p\le \dfrac{k}{i}<p+1\iff \dfrac{k}{p+1}<i\le \dfrac{k}{p}\)。

那么最大的 \(i\) 就很显然是 \([\dfrac{k}{p}]\) 了,也就是 \(\lfloor\dfrac{k}{\lfloor\frac{k}{l}\rfloor}\rfloor\)。

以上就是所有思路,但是在代码上还有要注意的地方。

首先注意 k / (k / l) 的结果可能会超过 \(n\) 导致多算了一些东西,会 WA。所以要取 \(\min\)。

然后注意在 k / l = 0 的时候一定要跳出循环,不然上面 k / (k / l) 直接除 \(0\) 了。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

ll n, k;
ll ans = 0;

int main() {
    cin >> n >> k;
    ans = n * k;
    for (int l = 1, r = 0; l <= n; l = r + 1) {
        if (k / l != 0)
            r = min(k / (k / l), n);
        else
            break;
        ans -= 1ll * (k / l) * (l + r) * (r - l + 1) / 2;
    }
    cout << ans << endl;
    return 0;
}

整除分块一般用来处理 \([x]\) 的问题。

标签:分块,cdot,dfrac,sum,sqrt,枚举,整除,ll
From: https://www.cnblogs.com/FLY-lai/p/18000525

相关文章

  • 数论分块
    将O(n)优化成o(根号n)[CQOI2007]余数求和题目描述给出正整数\(n\)和\(k\),请计算\[G(n,k)=\sum_{i=1}^nk\bmodi\]对于\(100\%\)的数据,保证\(1\leqn,k\leq10^9\)voidsolve(){ intn,k;cin>>n>>k; intans=n*k; //注意推导公式字母不要弄混 for(int......
  • 莫队算法/分块思想
    莫队算法/分块思想引入对于区间问题,常常会使用线段树维护,但是对于一些数据合并复杂度无法\(O(1)\)解决。所以不能使用,应当使用莫队算法。定义对于离线处理的查询问题,通过合理安排这些计算的次序,得到一个较优的复杂度例题1一个长度为\(n\)的序列,询问\(m\)次\([L,R]\)......
  • 一对一视频app开发,如何分块加载大文件?
    一对一视频app开发,如何分块加载大文件?后端:使用Koa2实现分块传输首先,在一对一视频app开发中,我们需要设置后端以支持分块传输编码。以下是使用Koa2的示例代码:constKoa=require("koa");constfs=require("fs");constapp=newKoa();app.use(async(ctx)=>......
  • 数论分块
    数论分块算法简介能够在\(\mathcal{O(\sqrt{n})}\)的时间复杂度内计算出含有\(\sum\limits_{i=1}^{n}\left\lfloor\frac{k}{i}\right\rfloor\)等式子。令\(a_i=\left\lfloor\frac{k}{i}\right\rfloor\),其主要思想为显然存在若干段连续区间内\(a_i\)值相同,......
  • P5048 [Ynoi2019 模拟赛] Yuno loves sqrt technology III(分块)
    题意简述多次询问区间众数的出现次数,强制在线。\(n,m\le5\times10^5\),时限\(2\)秒,空限\(62.5\)MB。分析弱化版本题相较弱化版有以下特点:空间复杂度要求\(O(n)\)时间复杂度要求严格\(O(n\sqrtn)\),也就是说\(O(n\sqrt{n\logn})\)过不掉。貌似所有5e5的分块都是......
  • Ybt 金牌导航 6.3.A. 区间众数 / P4168 [Violet] 蒲公英(分块)
    题意简述多次查询区间\([l,r]\)的众数,若有多个取数值最小的。强制在线。\(n\le4\times10^4,m\le5\times10^4\)。分析考虑分块。首先预处理出块区间内的众数\(maj_{l,r}\)和每种数在某个块的前缀的出现次数\(cnt_{i,a_i}\),时空复杂度都是\(O(n\sqrtn)\)的。对于询......
  • 【Django】通用分块上传
    通用分块上传文件importos#通用路径分块上传defpiecemeal_public_load(path,original_md5_hash,chunk_index,upload_file,chunk_total,file_Name):"""path:存放路径(media/后面跟的路径)original_md5_hash:临时文件夹名称chunk_inde......
  • abc096d<素数筛,整除>
    题目D-Five,FiveEverywhere寻找n个素数,使得这n个素数中任意5个数之和都是合数。思路如果一个数除5余1,那么5个这样的数之和一定能被5整除;筛出范围内所有满足上述条件,且为素数的数即可。总结如何想到除五余一这一点呢?首先应思考如何构造合数,想到如果是5个数之和,那么......
  • Flutter获取大文件MD5值的方法以及大文件实现分块上传和断点续传
    Flutter获取大文件MD5值的方法最近一直在搞flutter,有一个需求是将一个不到1G的大文件从App端上传到服务器,为了做文件校验所以要获取到文件的MD5。1.第一步首先获取到文件,并计算出文件大小和分快的数目Filefile=File(path);intfileSize=file.lengthSync();inttotalPart=......
  • 2023南海区信息学区赛(初中组) T1二进制整除
    第1题   二进制整除 查看测评数据信息交换二进制数相邻两个位置的数字,需要花费1元的代价。读入整数n以及n位二进制数(也许有前导0),你需要依次回答n个独立的问题,第i个问题(1<=i<=n)是这样的:假如要使得读入的二进制数是2^i的倍数,至少需要花费多少元的代价?如果不可能,则输出......