数论分块学习笔记

准备开始复习莫比乌斯反演,杜教筛这一部分,先复习一下数论分块

0.随便说说

数论分块可以计算如下形式的式子 ∑ i = 1 n f ( i ) g ( ⌊ n i ⌋ ) \sum_{i=1}^{n}f(i)g(\lfloor\frac{n}{i}\rfloor) i=1nf(i)g(⌊in⌋)
利用的原理是 ⌊ n i ⌋ \lfloor\frac{n}{i}\rfloor in的不同的值不超过 2 n 2\sqrt{n} 2n 个。
当我们可以在 O ( 1 ) O(1) O(1)的时间快速处理出 ∑ i = l r f ( i ) \sum_{i=l}^{r}f(i) i=lrf(i)或提前预处理出 f ( x ) f(x) f(x)的前缀和时,上述式子可在 O ( n ) O(\sqrt{n}) O(n )的时间计算出来。

1.代码实现

怎么找每个块是个问题,有个结论:
设块的左端点为 ⌊ n l ⌋ \lfloor\frac{n}{l}\rfloor ln,右端点为 ⌊ n r ⌋ \lfloor\frac{n}{r}\rfloor rn,则 r = ⌊ n ⌊ n l ⌋ ⌋ r=\lfloor\frac{n}{\lfloor\frac{n}{l}\rfloor}\rfloor r=lnn

证明也挺好证的 设 k = ⌊ n i ⌋ , k=\lfloor\frac{n}{i}\rfloor, k=in, k ≤ n i , k\le \frac{n}{i}, kin,
因此 ⌊ n k ⌋ ≥ ⌊ n n i ⌋ = i \lfloor\frac{n}{k}\rfloor\ge\lfloor\frac{n}{\frac{n}{i}}\rfloor=i kninn=i,即 i ≤ ⌊ n k ⌋ = ⌊ n ⌊ n i ⌋ ⌋ i\le\lfloor\frac{n}{k}\rfloor=\lfloor\frac{n}{\lfloor\frac{n}{i}\rfloor}\rfloor ikn=inn因此右端点 r = i m a x = ⌊ n ⌊ n i ⌋ ⌋ r=i_{max}=\lfloor\frac{n}{\lfloor\frac{n}{i}\rfloor}\rfloor r=imax=inn

因此每个块为 i = l i=l i=l i = ⌊ n ⌊ n i ⌋ ⌋ i=\lfloor\frac{n}{\lfloor\frac{n}{i}\rfloor}\rfloor i=inn

在这里插入图片描述

2.例题

先顺手把 O I    W i k i OI\,\,Wiki OIWiki上的三个例题做了吧

UVA11526 H(n)

题面
用洛谷的题面了,这题就是求 ∑ i = 1 n ⌊ n i ⌋ \sum_{i=1}^{n}\lfloor\frac{n}{i}\rfloor i=1nin,就是板子题,相当于 f ( x ) = 1 , g ( n / i ) = n / i f(x)=1,g(n/i)=n/i f(x)=1,g(n/i)=n/i。注意如果 n = 2147483647 n=2147483647 n=2147483647,最后一次 n x t + 1 nxt+1 nxt+1会爆 i n t int int U V A UVA UVA神奇 o j oj oj会报 R E RE RE,所以就都开 l o n g    l o n g long\,\,long longlong就行,时间复杂度 O ( T n ) O(T\sqrt{n}) O(Tn )

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int t,n;
int main(){
    cin>>t;
    while(t--){
        cin>>n;
        ll nxt=0,ans=0;
        for(ll i=1;i<=n;i=nxt+1){
            nxt=n/(n/i);
            ans+=(nxt-i+1)*(n/i);
        }
        cout<<ans<<endl;
    }
}

P2261 [CQOI2007] 余数求和

题面
Solution
O I OI OI时期的博客有这道题,题解挂链接了,随手一推就是这样,减号左边是 n k , nk, nk,右侧用数论分块做

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,k,ans,nxt,sum;
inline ll s(ll n){
    return n*(n+1)/2;
}
int main(){
    cin>>n>>k;
    ans=n*k;
    for(int i=1;i<=min(n,k);i=nxt+1){
        nxt=min(k/(k/i),n);
        sum+=(s(nxt)-s(i-1))*(k/i);
    }
    cout<<ans-sum<<endl;
}

P3455 [POI2007] ZAP-Queries

题面

最后用个二维数论分块就可
闲得没事 这题想多打几个空格

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e4 + 100;
int cnt, pri[maxn], mu[maxn], s_mu[maxn];
bool vis[maxn];
inline void read(int &x) {
    int s = 0, w = 1; char ch = getchar();
    while (ch < '0' || ch > '9') {if(ch == '-') w = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') {s = (s << 3) + (s << 1) + (ch & 15); ch = getchar(); }
    x = s * w;
}
void setup() {
    mu[1] = 1;
    for (int i = 2; i <= maxn - 100; i++) {
        if(!vis[i]) pri[++cnt] = i, mu[i] = -1;
        for (int j = 1; j <=cnt && i * pri[j] <= maxn - 100; j++) {
            vis[i * pri[j]] = true;
            if(i % pri[j]) mu[i * pri[j]] = -mu[i];
            else {
                mu[i * pri[j]] = 0;
                break;
            }
        }
    }
    for (int i = 1; i <= maxn - 100; i++) s_mu[i] = s_mu[i - 1] + mu[i];
}
int T, a, b, d, nxt;
int main() {
    setup();
    read(T);
    while(T--) {
        read(a), read(b), read(d);
        a /= d, b /= d;
        if(a > b) a ^= b, b ^= a, a ^= b;
        ll ans = 0;
        for (int i = 1; i <= a; i = nxt + 1) {
            nxt = min(a / (a / i), b / (b / i));
            ans += 1ll * (s_mu[nxt] - s_mu[i - 1]) * (a / i) * (b / i);
        }
        printf("%lld\n", ans);
    }
}

放两道套路题,这一类题都是以 ∑ i = 1 n ∑ j = 1 n f ( g c d ( i , j ) ) \sum_{i=1}^{n}\sum_{j=1}^{n}f(gcd(i,j)) i=1nj=1nf(gcd(i,j))形式的,我们要将 g c d ( i , j ) gcd(i,j) gcd(i,j)提出来,作如下变化:

然后求出 f ( x ) , ϕ ( x ) f(x),\phi(x) f(x),ϕ(x)的前缀和并应用数论分块解决。
后面两题的数据范围不一样,第一题是 n ≤ 1 e 7 n\le 1e7 n1e7,第二题是 n ≤ 1 e 9 n\le 1e9 n1e9,前者可以应用朴素的筛法求出欧拉函数前缀和,后者要用到杜教筛进行求解。

bzoj4804 欧拉心算

题面
请添加图片描述
预处理出欧拉函数前缀和,应用数论分块即可。
写错了,最后是 s u m ϕ ( n ) sum\phi(n) sumϕ(n)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 1e7 + 10;
int cnt, pri[maxn], euc[maxn];
ll s[maxn];
bool vis[maxn];
void setup(){
    euc[1] = 1;
    for (int i = 2; i <= maxn - 10; i++) {
        if (!vis[i]) pri[++cnt] = i, euc[i] = i - 1;
        for (int j = 1; j <= cnt && i * pri[j] <= maxn - 10; j++) {
            vis[i * pri[j]] = true;
            if (i % pri[j]) euc[i * pri[j]] = euc[i] * (pri[j] - 1);
            else {
                euc[i * pri[j]] = pri[j] * euc[i];
                break;
            }
        }
    }
    for (int i = 1; i <= maxn - 10; i++) s[i] = s[i - 1] + euc[i];
}
int T, n;
int main() {
    setup();
    scanf("%d", &T);
    while (T--) {
        scanf("%d", &n);
        int nxt = 0; ll ans = 0;
        for (int i = 1; i <= n; i = nxt + 1) {
            nxt = n / (n / i);
            ans += (s[nxt] - s[i - 1]) * s[n / i];
        }
        printf("%lld\n", 2ll * ans - s[n]);
    }
}

HDU7325 GCD Magic

题面
考场上考到得,打了 150 150 150行, M L E MLE MLE了一次, W A WA WA了一次,最后过了
M L E MLE MLE是因为对 s b H D U O J sbHDUOJ sbHDUOJ不信任,预处理的 1 e 7 1e7 1e7的欧拉函数前缀和,后来改成了 2 e 6 2e6 2e6 W A WA WA了,看了一会儿发现是因为杜教筛欧拉函数前缀和没模 m o d mod mod导致后面计算答案时候爆 l o n g    l o n g long\,\,long longlong了,改过来交一发对了,太不容易了,这要再错真不知道要 d e b u g debug debug到哪年去。
思路如下,就不打公式了,太多了,手写了。
请添加图片描述
上代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 998244353;
const int maxn = 2000010;
inline void read(int &x)
{
    int s = 0, w = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            w = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
    {
        s = (s << 3) + (s << 1) + (ch & 15);
        ch = getchar();
    }
    x = s * w;
}
ll ans, s[maxn], frac[20], fracinv[20];
int t, n, k, lst;
ll pri[maxn], euc[maxn], cur, mu[maxn], sum_mu[maxn];
bool vis[maxn];
map<ll, ll> mp_mu;

ll S_mu(ll x)
{
    if (x < maxn)
        return sum_mu[x];
    if (mp_mu[x])
        return mp_mu[x];
    ll ret = (ll)1;
    for (ll i = 2, j; i <= x; i = j + 1)
    {
        j = x / (x / i);
        ret -= S_mu(x / i) * (j - i + 1);
    }
    return mp_mu[x] = ret % mod;
}

ll S_phi(ll x)
{
    ll ret = (ll)0;
    ll j;
    for (ll i = 1; i <= x; i = j + 1)
    {
        j = x / (x / i);
        ret += (S_mu(j) - S_mu(i - 1)) * (x / i) * (x / i);
    }
    return ((ret - 1) / 2 + 1) % mod;
}
inline ll qpow(ll x, ll y)
{
    ll re = 1LL;
    while (y)
    {
        if (y & 1)
            (re *= x) %= mod;
        (x *= x) %= mod;
        y >>= 1;
    }
    return re;
}
inline ll inv(ll x)
{
    return qpow(x, mod - 2);
}
void setup()
{
    frac[0] = fracinv[0] = 1LL;
    for (int i = 1; i <= 15; i++)
        frac[i] = 1ll * frac[i - 1] * i % mod;
    fracinv[15] = inv(frac[15]);
    for (int i = 14; i; i--)
        fracinv[i] = 1ll * fracinv[i + 1] * (i + 1) % mod;
    euc[1] = 1;
    mu[1] = 1;
    for (int i = 2; i < maxn; i++)
    {
        if (!vis[i])
        {
            pri[++cur] = i;
            mu[i] = -1;
            euc[i] = i - 1;
        }
        for (int j = 1; j <= cur && i * pri[j] < maxn; j++)
        {
            vis[i * pri[j]] = true;
            if (i % pri[j])
                mu[i * pri[j]] = -mu[i], euc[i * pri[j]] = euc[i] * euc[pri[j]];
            else
            {
                mu[i * pri[j]] = 0;
                euc[i * pri[j]] = euc[i] * pri[j];
                break;
            }
        }
    }

    for (int i = 1; i < maxn; i++)
        s[i] = (1ll * s[i - 1] + euc[i]) % mod;
    for (int i = 1; i < maxn; i++)
        sum_mu[i] = (1ll * sum_mu[i - 1] + mu[i]) % mod;
}
inline ll C(ll n, ll m)
{
    if (n < m)
        return 0;
    return 1ll * frac[n] * fracinv[m] % mod * fracinv[n - m] % mod;
}
inline ll seq(ll n, ll k)
{
    if (k == 0)
        return n;
    ll a1 = (1LL << k) % mod, q = (1LL << k) % mod;
    return 1LL * a1 * ((qpow(q, n) - 1 + mod) % mod) % mod * inv((q - 1 + mod) % mod) % mod;
}
inline ll sg(ll n, ll k)
{
    if (n == 0)
        return 0LL;
    ll ans = 0, flag = 1;
    for (int i = 0; i <= k; i++)
    {
        ans = (1ll * ans + 1ll * ((flag + mod) % mod) * C(k, i) % mod * seq(n, k - i) % mod) % mod;
        flag *= (-1ll);
    }
    return ans % mod;
}
int main()
{
    setup();
    read(t);
    while (t--)
    {
        read(n), read(k);
        ans = 0ll;
        lst = 0;
        for (int i = 1; i <= n; i = lst + 1)
        {
            lst = n / (n / i);
            ll snow = 0;
            if (n / i >= maxn - 10)
                snow = S_phi(n / i);
            else
                snow = s[n / i];
            ans = (1ll * ans + (1ll * sg(lst, k) - sg(i - 1, k) + mod) % mod * snow % mod) % mod;
        }
        printf("%lld\n", (2LL * ans % mod - sg(n, k) + mod) % mod);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/57708.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

GoogLeNet卷积神经网络-笔记

GoogLeNet卷积神经网络-笔记 GoogLeNet是2014年ImageNet比赛的冠军&#xff0c; 它的主要特点是网络不仅有深度&#xff0c; 还在横向上具有“宽度”。 由于图像信息在空间尺寸上的巨大差异&#xff0c; 如何选择合适的卷积核来提取特征就显得比较困难了。 空间分布范围更广的…

采集数据筛选-过滤不要数据或只保留指定数据

采集文章数据&#xff0c;有时候会遇到一些不需要采集的数据&#xff0c;或者只想采集一些特定的数据&#xff0c;可以使用简数采集器的内容过滤功能&#xff0c;对采集的数据进行筛选&#xff0c;只有符合的数据才采集保留。 可以用于过滤掉一些广告、专题、网站首页等无效数…

ESD防静电监控系统在SMT产线中的应用案例

作为电子厂的关键制造环节之一&#xff0c;SMT&#xff08;表面贴装技术&#xff09;产线的效率和质量对企业的竞争力至关重要。为了提高生产线的管理效率和保障生产环境的质量&#xff0c;许多电子厂开始采用MES生产管理系统和ESD防静电监控系统的综合解决方案。 在SMT产线中安…

SpringBoot项目增加logback日志文件

一、简介 在开发和调试过程中&#xff0c;日志是一项非常重要的工具。它不仅可以帮助我们快速定位和解决问题&#xff0c;还可以记录和监控系统的运行状态。Spring Boot默认提供了一套简单易用且功能强大的日志框架logback&#xff0c;本文将介绍如何在Spring Boot项目中配置和…

无涯教程-Perl - 循环语句

在某些情况下&#xff0c;您需要多次执行一个代码块。通常&#xff0c;语句是按顺序执行的:函数中的第一个语句首先执行&#xff0c;然后第二个执行&#xff0c;依此类推。 Perl编程语言提供了以下类型的循环来处理循环需求。 Sr.No.Loop Type & 描述1 while loop在给定条…

浅谈大数据软件的功能性分析

在当今时代的潮流中&#xff0c;工作中遇到大数据处理的时候非常多&#xff0c;因此需要一些大数据分析软件帮助人们进行工作。由于这些软件针对的对象不同&#xff0c;因此使用方法也不同&#xff0c;那么为了帮助更多的人了解大数据分析软件&#xff0c;我们就对这些软件的功…

Spring Cloud+Spring Boot+Mybatis+uniapp+前后端分离实现知识付费平台免费搭建 qt

&#xfeff;Java版知识付费源码 Spring CloudSpring BootMybatisuniapp前后端分离实现知识付费平台 提供职业教育、企业培训、知识付费系统搭建服务。系统功能包含&#xff1a;录播课、直播课、题库、营销、公司组织架构、员工入职培训等。 提供私有化部署&#xff0c;免费售…

【3维视觉】3D空间常用算法(点到直线距离、面法线、二面角)

3D空间点到直线的距离 3D空间点到直线的距离 3D空间的曲率 三维空间有三个基本元素&#xff0c;点&#xff0c;线&#xff0c;面。那么曲率是如何定义的呢&#xff1f; 点的曲率&#xff1f; 线的曲率&#xff1f; 面的曲率&#xff1f; 法曲率 设曲面上的曲线在某一点处的切…

prometheus+grafana进行服务器资源监控

在性能测试中&#xff0c;服务器资源是值得关注一项内容&#xff0c;目前&#xff0c;市面上已经有很多的服务器资 源监控方法和各种不同的监控工具&#xff0c;方便在各个项目中使用。 但是&#xff0c;在性能测试中&#xff0c;究竟哪些指标值得被关注呢&#xff1f; 监控有…

Git下:Git命令使用-详细解读

今天给大家讲一讲 Git常用命令的使用说明&#xff0c;希望本篇文章对大家有所帮助。 一、Git 安装 Git 的详细安装教程&#xff1a;见上一篇文章《Git上&#xff1a;Git安装教程》&#xff1a; Git上&#xff1a;全网最全最详细的Git安装教程&#xff0c;建议收藏保存 二、…

TDosCommand 组件来执行 JavaScript 脚本(nodejs)

可以在 Delphi 中使用 TDosCommand 组件来执行 JavaScript 脚本。但是&#xff0c;由于 JavaScript 是一种脚本语言&#xff0c;它通常在浏览器中运行&#xff0c;因此您需要使用一种 JavaScript 引擎来执行 JavaScript 脚本。常见的 JavaScript 引擎有 Node.js、Rhino、V8 等等…

面试题学习以及问题

redis redis缓存 缓存穿透 布隆过滤器主要是用于检索一个元素是否在一个集合中。我们当时使用的是 redisson实现的布隆过滤器。 它的底层主要是先去初始化一个比较大数组&#xff0c;里面存放的二进制0或1。在一 开始都是0&#xff0c;当一个key来了之后经过3次hash计算&…

vscode配置c++环境

第一步&#xff1a;安装vscode编辑器 预先安装&#xff1a; vscode&#xff08;https://code.visualstudio.com/&#xff09;在vscode中安装 C/C extension for VS Code&#xff08;在左侧扩展栏中搜索 “C”&#xff09; 第二步&#xff1a;安装MinGW-w64工具链 MinGW 提供…

超详情的开源知识库管理系统- mm-wiki的安装和使用

背景&#xff1a;最近公司需要一款可以记录公司内部文档信息&#xff0c;一些只是累计等&#xff0c;通过之前的经验积累&#xff0c;立马想到了 mm-wiki&#xff0c;然后就给公司搭建了一套&#xff0c;分享一下安装和使用说明&#xff1a; 当前市场上众多的优秀的文档系统百…

VBA技术资料MF36:VBA_在Excel中排序

【分享成果&#xff0c;随喜正能量】一个人的气质&#xff0c;并不在容颜和身材&#xff0c;而是所经历过的往事&#xff0c;是内在留下的印迹&#xff0c;令人深沉而安谧。所以&#xff0c;优雅是一种阅历的凝聚&#xff1b;淡然是一段人生的沉淀。时间会让一颗灵魂&#xff0…

设置系统编码 Beta

在yolov5环境搭建过程中会遇到如下的编码错误警告&#xff1a; 这时&#xff0c;按住“ctrlc”中止进程&#xff0c;然后设置系统编码&#xff1a; 电脑右键属性打开&#xff1a; 重启之后等安装好了&#xff0c;记得回去把bae键取消。

Ansible自动化运维工具 —— Playbook 剧本

playbooks 本身由以下各部分组成 &#xff08;1&#xff09;Tasks&#xff1a;任务&#xff0c;即通过 task 调用 ansible 的模板将多个操作组织在一个 playbook 中运行 &#xff08;2&#xff09;Variables&#xff1a;变量 &#xff08;3&#xff09;Templates&#xff1a;模…

iOS——Block one

块类似于匿名函数或闭包&#xff0c;在许多其他编程语言中也存在类似的概念。 可以访问上下文&#xff0c;运行效率高 Block 以下是块的一些基本知识&#xff1a; 块的定义&#xff1a;块是由一对花括号 {} 包围的代码片段&#xff0c;可以包含一段可执行的代码。块的定义使…

Stable Diffusion - Stable Diffusion WebUI 支持 SDXL 1.0 模型的环境配置

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132056980 SDXL 1.0 版本 是 Stable Diffusion 的最新版本&#xff0c;是基于潜在扩散模型的文本到图像生成技术&#xff0c;能够根据输入的任何文…

机器学习知识经验分享之六:决策树

python语言用于深度学习较为广泛&#xff0c;R语言用于机器学习领域中的数据预测和数据处理算法较多&#xff0c;后续将更多分享机器学习数据预测相关知识的分享&#xff0c;有需要的朋友可持续关注&#xff0c;有疑问可以关注后私信留言。 目录 一、R语言介绍 二、R语言安装…