当前位置: 首页 > news >正文

导览项目KD-Tree最近地点搜索优化

背景描述

我在做一个校园导览的小程序的时候,涉及到最近地点搜索的业务功能,根据当前位置搜索最近的校园地点,比如教学楼,图书馆,自习室,办事地点等等。

在这里插入图片描述

我最初想到的办法就是获取用户当前位置的经纬度后,遍历数据库中所有或指定分类校园地点,逐一计算球面距离,再通过排序返回最近的结果。虽然对于该项目来说,校园地点也不会太多,该方法完全可行,但秉持着探索的精神,我想要去寻找效率最高的办法

问题探索

问题分析

校园地点的经纬度本质上是二维空间中的点集。暴力搜索的低效,主要是因为忽略了空间数据的两个核心特征:

  • 空间局部性:相邻地点在物理空间上往往聚集(如教学楼群、宿舍区),可批量筛选而非逐个计算。
  • 维度独立性:经度与纬度具有正交性,可通过坐标轴交替划分空间,快速缩小搜索范围。

这就像在一座图书馆找书——暴力法需要逐本翻阅所有书架,而聪明人会先查看楼层索引图,直接锁定目标区域。

因此对于这个问题的解决需要使用空间索引算法,通过预处理将无序的地理数据组织成高效查询的结构,这一过程类似于为字典添加目录——前期花时间编排字母顺序,后期查词时无需逐页翻找。

算法选择

明确了目标之后,我就去比较寻找合适的空间索引算法:

算法优势局限性适用场景
KD-Tree实现简单、静态数据查询快、内存占用低动态更新需重建树,高维性能下降低频更新地点
R-Tree支持动态插入删除、适合范围查询实现复杂,节点重叠降低查询效率地图实时编辑
Geohash编码简单、兼容数据库精度受网格大小限制,边界点易漏粗略地理位置匹配

对于我的项目应用场景来说,地点数据相对固定(学期内建筑位置不变),且需要频繁触发高精度最近地点查询,所以我选择了KD-Tree算法来计算。

本项目场景下KD-Tree算法优势:

  • 静态数据友好:一次构建索引,长期复用,适合校园地点的低频更新。
  • 查询效率极致:通过二叉树层级跳转,剪枝查询,效率高,时间复杂度可达O(log n)。
  • 内存开销可控:无需存储冗余空间结构,适合轻量化的小程序后端。

算法原理

KD-Tree算法的核心数据结构是一个二叉树,每个节点代表一个超矩形区域,将多维空间递归分割,这样在查询的时候可以利用二叉树剪枝快速排除一部分待搜索目标。

分割规则

  • 按维度轮流划分(如先按x轴,再按y轴,循环往复)。
  • 选择当前维度的中位数作为分割点,保证树平衡。

但因为按照维度下排序进行分割,变相损失了一部分精度,所以在进行常规二叉树搜索的时候,还需要额外回溯检查其他子树是否可能存在更近的点(通过比较超球面与分割面的距离),以保证最后算出来的是真正最近的点。

代码实现

构建KD-Tree

二叉树Node节点Class

class KDNode {Point2D.Double point;  // 校园地点pointKDNode left;           // 左子树(x或y较小的点)KDNode right;          // 右子树(x或y较大的点)KDNode(Point2D.Double point) {this.point = point;}
}

构建KD-Tree,可以将其存放于Redis中,提前构建好,进一步加快算法搜索速度,有地点更新时再重新构建

public class KDTree {private KDNode root;public KDTree(List<Point2D.Double> points) {root = buildTree(points, 0);}private KDNode buildTree(List<Point2D.Double> points, int depth) {if (points.isEmpty()) return null;// 按当前维度排序int axis = depth % 2;points.sort(Comparator.comparingDouble(p -> axis == 0 ? p.getX() : p.getY()));int medianIndex = points.size() / 2;	// 找到中位数作为根节点KDNode node = new KDNode(points.get(medianIndex));// 构建左右子树node.left = buildTree(points.subList(0, medianIndex), depth + 1);node.right = buildTree(points.subList(medianIndex + 1, points.size()), depth + 1);return node;}
}

最近地点搜索

public Point2D.Double findNearest(Point2D.Double target) {return findNearest(root, target, 0, null);
}private Point2D.Double findNearest(KDNode node, Point2D.Double target, int depth, Point2D.Double best) {if (node == null) return best;// 更新最近点double currentDist = node.point.distanceSq(target);double bestDist = best == null ? Double.POSITIVE_INFINITY : best.distanceSq(target);if (currentDist < bestDist) {best = node.point;}// 决定搜索方向int axis = depth % 2;boolean isLeftBranch = (axis == 0 ? target.getX() : target.getY()) < (axis == 0 ? node.point.getX() : node.point.getY());KDNode nextBranch = isLeftBranch ? node.left : node.right;KDNode otherBranch = isLeftBranch ? node.right : node.left;// 优先搜索更近的分支best = findNearest(nextBranch, target, depth + 1, best);// 检查另一分支是否可能有更近的点,根据当前位置到目标维度分割线的垂直距离来做判断// 如果目标维度垂直距离大于当前最短距离,则另一分支不可能有更短的距离double axisDist = axis == 0 ? Math.pow(target.getX() - node.point.getX(), 2) : Math.pow(target.getY() - node.point.getY(), 2);if (axisDist < bestDist) {best = findNearest(otherBranch, target, depth + 1, best);}return best;
}

相关文章:

导览项目KD-Tree最近地点搜索优化

背景描述 我在做一个校园导览的小程序的时候&#xff0c;涉及到最近地点搜索的业务功能&#xff0c;根据当前位置搜索最近的校园地点&#xff0c;比如教学楼&#xff0c;图书馆&#xff0c;自习室&#xff0c;办事地点等等。 我最初想到的办法就是获取用户当前位置的经纬度后&…...

【Pandas】pandas DataFrame rmul

Pandas2.2 DataFrame Binary operator functions 方法描述DataFrame.add(other)用于执行 DataFrame 与另一个对象&#xff08;如 DataFrame、Series 或标量&#xff09;的逐元素加法操作DataFrame.add(other[, axis, level, fill_value])用于执行 DataFrame 与另一个对象&…...

苹果(IOS)手机怎么开启开发者模式(简单明了版)

苹果手机怎么开启开发者模式&#xff08;简单明了版&#xff09; iOS 16 以后&#xff0c;苹果新增了「开发者模式」。如果你要在 iPhone 上运行自己开发的 App&#xff0c;比如通过 Xcode 或其它工具安装测试包&#xff0c;必须先开启这个模式。 下面是开启方法&#x1f447…...

Agent2Agent

rag系列文章目录 文章目录 rag系列文章目录前言一、协议设计原则与技术基础二、通信机制与消息格式三、身份验证与安全设计四、能力发现与任务协作总结 前言 谷歌于2025年4月推出了A2A&#xff08;Agent2Agent&#xff09;协议&#xff0c;旨在解决当前AI智能体生态中的互操作…...

【MCP】了解远程MCP调用背后使用的SSE协议

本文介绍了远程MCP使用的SSE协议&#xff0c;通过wireshark抓包的方式了解MCP客户端和服务端之间通过SSE协议交互涉及到的请求与响应。 1. 什么是SSE协议&#xff1f; 参考&#xff1a;https://zhuanlan.zhihu.com/p/1894024642395619635和https://blog.csdn.net/aerror/artic…...

Log4j Properties 配置项详细说明

Log4j Properties 配置项详细说明 1. 核心配置项说明 根日志记录器&#xff1a;定义全局日志级别和输出目标 log4j.rootLogger [级别], appender1, appender2,...Appender 定义&#xff1a;指定日志输出目标&#xff08;控制台、文件等&#xff09; log4j.appender.[名称].[属…...

哪些物联网框架支持多协议接入?选型指南与核心能力解析

在物联网&#xff08;IoT&#xff09;领域&#xff0c;设备通信协议的多样性&#xff08;如MQTT、CoAP、Modbus、Zigbee等&#xff09;是开发者面临的核心挑战之一。选择支持多协议接入的物联网框架&#xff0c;可以显著降低异构设备连接的复杂度&#xff0c;提升系统的兼容性和…...

第三方测试机构如何保障软件质量并节省企业成本?

在软件行业&#xff0c;第三方测试机构扮演着极其重要的角色。他们提供独立且专业的测试服务&#xff0c;目的是为了保障软件的质量以及提升用户的使用体验。 专业独立 测试机构拥有经验丰富的测试员和严谨的测试流程。他们会对软件各项功能进行细致检验&#xff0c;力求不放…...

Eigen迭代求解器类

1. 迭代求解器核心类概览 Eigen 提供多种迭代法求解稀疏线性方程组 AxbAxb&#xff0c;适用于大规模稀疏矩阵&#xff1a; 求解器类适用矩阵类型算法关键特性ConjugateGradient对称正定&#xff08;SPD&#xff09;共轭梯度法&#xff08;CG&#xff09;高精度&#xff0c;内…...

AI 与高性能计算的深度融合:开启科技新纪元

在当今科技迅猛发展的时代&#xff0c;人工智能&#xff08;AI&#xff09;与高性能计算&#xff08;HPC&#xff09;正以前所未有的态势深度融合&#xff0c;这种融合宛如一场强大的风暴&#xff0c;席卷并重塑着众多领域的格局。从科学研究的突破到商业应用的革新&#xff0c…...

写入cache时数据格式错误产生的ERRO导致整个测试框架无法运行

背景 在yaml文件里面提取request放入缓存时&#xff0c;request是form-data&#xff0c;错用jsonpath提取并写入缓存&#xff0c;导致后面的所有运行都异常 原因 起因是我想引用请求体的Uid&#xff0c;提取方式用错了&#xff0c;所以可以看到最后一段current_request_set_…...

3:QT联合HALCON编程—海康相机SDK二次程序开发

思路&#xff1a; 1.定义带UI界面的主函数类 1.1在主函数中包含其它所有类头文件&#xff0c;进行声明和实例化&#xff1b;使用相机时&#xff0c;是用公共相机的接口在某一个具体函数中去实例化具体的海康相机对象。 1.2设计界面&#xff1a;连接相机&#xff0c;单次采集&a…...

图论---LCA(倍增法)

预处理 O( n logn )&#xff0c;查询O( log n ) #include<bits/stdc.h> using namespace std; typedef pair<int,int> pii; const int N40010,M2*N;//是无向边&#xff0c;边需要见两边int n,m; vector<int> g[N]; //2的幂次范围 0~15 int depth[N],fa[N][1…...

Bento4的安装和简单转码

1.下载Bento4 2解压复制到安装位置 3配置环境变量 在path下配置 5.视频转码为Dash 视频分片化 mp4fragment --track video --fragment-duration 4000 C:\Users\zcc\Downloads\Video\gg.mp4 C:\Users\zcc\Downloads\Video\out3\input_fragmented.mp4分片化的视频转码为dash…...

用python写一个相机选型的简易程序

最近有点忙&#xff0c;上来写的时间不多。 今天就把之前写的一个选型的简易程序&#xff0c;供大家参考。 代码&#xff1a; import sys from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,QLabel, QLineEdit, QPushButton, QGro…...

论人际关系发展的阶段

朋友关系的建立和发展是一个渐进的过程&#xff0c;通常需要经历情感积累、信任磨合和价值观融合等阶段。以下是朋友关系发展的详细阶段划分及核心特征&#xff1a; 一、表层接触阶段&#xff08;社交试探期&#xff09; 核心特征&#xff1a;以信息交换为主&#xff0c;关系停…...

2软考系统架构设计师:第一章系统架构概述 - 练习题附答案及超详细解析

第一章系统架构概述综合知识单选题 每道题均附有答案解析&#xff1a; 1. 系统架构的核心定义是什么&#xff1f; A. 系统代码的实现细节 B. 系统组件、组件关系及与环境交互的高层次设计蓝图 C. 用户界面的设计规范 D. 数据库表结构的详细设计 答案&#xff1a;B 解析&…...

华为OD机试真题——素数之积RSA加密算法(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳实现

2025 A卷 100分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C、GO六种语言的最佳实现方式&#xff1b; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析&#xff1b; 本文收录于专栏&#xff1a;《2025华为OD真题目录…...

k8s中资源的介绍及标准资源namespaces实践

文章目录 第1章 k8s中的资源(resources)介绍1.1 k8s中资源(resouces)的分类1.2 k8s中资源(resources)的级别1.3 k8s中资源(resources)的API规范1.4 k8s中资源(resources)的manifests 第2章 k8s中的标准资源之namespaces的实践2.1 基本介绍2.2 编写相关ns资源对象的manifests2.3…...

k8s学习记录(四):节点亲和性

一、前言 在上一篇文章里&#xff0c;我们了解了 Pod 中的nodeName和nodeSelector这两个属性&#xff0c;通过它们能够指定 Pod 调度到哪个 Node 上。今天&#xff0c;我们将进一步深入探索 Pod 相关知识。这部分内容不仅信息量较大&#xff0c;理解起来也有一定难度&#xff0…...

联想笔记本电脑在Windows下通过联想驱动实现风扇控制

概述 本文旨在解决部分联想笔记本电脑无法使用主流的风扇控制工具&#xff08;如Fan Control, SpeedFan&#xff09;控制风扇的问题。主流的风扇控制工具在这些电脑上会因无法找到控制风扇的EC寄存器而无法发挥作用。但这是不是就意味着没办法控制风扇了呢&#xff1f;答案是否…...

Java单链表题目

Java链表题目练习 移除链表元素反转单链表链表的中间节点返回倒数第K个节点合并两个有序列表判断链表是否回文 学习了知识&#xff0c;就要进行其检验自己是否真正学会&#xff0c;练习题目来加强对知识的理解&#xff0c;今天就来练习一下链表题目 移除链表元素 目的&#xff…...

springboot入门-controller层

在 Spring Boot 中&#xff0c;Controller 层是处理 HTTP 请求的核心组件&#xff0c;负责接收客户端请求、调用业务逻辑&#xff08;Service 层&#xff09;并返回响应。其核心原理基于 Spring MVC 框架&#xff0c;通过注解驱动的方式实现请求的路由和参数绑定。以下是 Contr…...

游戏引擎学习第245天:wglChoosePixelFormatARB

Blackboard: PBO&#xff08;像素缓冲对象&#xff09; 我们将一起编写一个完整的游戏。老实说&#xff0c;我原本以为我们会花更长时间来实现异步纹理上传&#xff0c;结果我们只用了两天时间&#xff0c;主要原因是我们没有设置标志来真正告诉程序下载纹理&#xff0c;所以这…...

中国大陆DNS服务选择指南:阿里云VS AWS,合规性与最佳实践

导语 在中国大陆开展互联网业务时,DNS服务的选择不仅关乎性能,更涉及合规性问题。本文将深入探讨DNS服务商选择的自由度、阿里云与AWS DNS服务的优劣势,以及如何在确保合规的同时优化您的域名解析策略。无论您是初创公司还是跨国企业,这份指南都将助您在复杂的中国互联网环境中…...

LLaMa Factory大模型微调

LLaMa Factory大模型微调 大模型微调平台&硬件LLaMA-Factory安装hfd下载hugging face模型自我认知微调Alpaca数据集指令监督微调断点续训 大模型微调 微调自我认知微调特定领域数据集。 平台&硬件 Ubuntu20.04显卡&#xff1a;M40 24G 2080TI 22G微调框架&#xff…...

git和github的使用指南

目录 1.git初始化本地仓库 2.远程仓库 3.如何将自己的代码上传到远程仓库的某一个分支 1.git初始化本地仓库 在项目目录中初始化 Git 仓库&#xff1a; cd your-project-directory git init 将文件添加到暂存区&#xff1a; git add . //添加所有文件 git add <fi…...

如何快速轻松地恢复未保存的 Word 文档:简短指南

文字处理器已经存在了几十年&#xff0c;其中许多已经变得非常擅长防止问题。丢失未保存的数据是一个常见问题&#xff0c;因此办公软件通常带有恢复文件的方法。在本文中&#xff0c;我们将介绍如何恢复 Word 文档&#xff0c;即使您尚未保存它。 确保数据安全的最佳方法是保…...

【Linux网络】打造初级网络计算器 - 从协议设计到服务实现

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;博客仓库&#xff1a;https://gitee.com/JohnKingW/linux_test/tree/master/lesson &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &…...

基于STM32定时器中断讲解(HAL库)

基于STM32定时器中断讲解&#xff08;HAL库&#xff09; 1、定时器简单介绍 以STM32F103C8T6中几个定时器为例&#xff1a; TIM1&#xff1a;这是一个高级定时器&#xff0c;不仅具备基本的定时中断功能&#xff0c;还拥有内外时钟源选择、输入捕获、输出比较、编码器接口以…...

《Vue3学习手记5》

pinia 共享的数据交给集中状态管理 引入与使用 //main.ts // 引入Pinia import {createPinia} from "pinia"const piniacreatePinia() app.use(pinia)案例&#xff1a; <template><div class"count"><h2>当前和为&#xff1a;{{ sum…...

MySQL多查询条件下深度分页性能优化技巧及示例总结

深度分页(Deep Pagination)是MySQL中常见的性能瓶颈问题,特别是在多查询条件下,当offset值很大时,查询性能会急剧下降。本文将总结多种优化技巧,并提供实际示例。 一、深度分页的性能问题分析 当执行类似SELECT * FROM table WHERE condition1 AND condition2 LIMIT 1000…...

3、初识RabbitMQ

界面上的导航栏共分6部分&#xff0c;分别代表不同的意思 一、Producer和Consumer Producer: 生产者, 是RabbitMQ Server的客户端, 向RabbitMQ发送消息 Consumer: 消费者, 也是RabbitMQ Server的客⼾端, 从RabbitMQ接收消息 Broker&#xff1a;其实就是RabbitMQ Server, 主要…...

量子计算与GPU的异构加速:基于CUDA Quantum的混合编程实践

一、量子模拟的算力困境与GPU破局 量子计算模拟面临‌指数级增长的资源需求‌&#xff1a;n个量子比特的态向量需要存储2^n个复数。当n>30时&#xff0c;单机内存已无法承载&#xff08;1TB需求&#xff09;。传统CPU模拟器&#xff08;如Qiskit Aer&#xff09;在n28时计算…...

在Spring Boot项目中实现Word转PDF并预览

在Spring Boot项目中实现Word转PDF并进行前端网页预览&#xff0c;你可以使用Apache POI来读取Word文件&#xff0c;iText或Apache PDFBox来生成PDF文件&#xff0c;然后通过Spring Boot控制器提供文件下载或预览链接。以下是一个示例实现步骤和代码&#xff1a; 1. 添加依赖 …...

Windows怎样使用curl下载文件

安装curl 从官网下载&#xff1a;访问curl官方网站&#xff0c;根据系统位数&#xff08;32 位或 64 位&#xff09;选择相应的版本进行下载。下载完成后&#xff0c;双击安装程序并按照提示进行安装。也可以选择自定义安装路径&#xff0c;记住安装路径&#xff0c;后续配置环…...

priority_queue的学习

priority_queue的介绍 优先级队列是一种容器适配器&#xff0c;根据严格的弱排序标准&#xff0c;它的第一个元素总是它所包含的元素中最大的。此上下文类似于堆&#xff0c;在堆中可以随时插入元素&#xff0c;并且只能检索最大堆元素(优先队列中位于顶部的元素)。优先队列被…...

浅谈Java 内存管理:栈与堆,垃圾回收

在Java编程世界里&#xff0c;内存管理是一项极为关键的技能&#xff0c;它就像程序运行背后的“隐形守护者”&#xff0c;默默影响着程序的性能与稳定性。今天&#xff0c;咱们就来简单学习一下Java内存管理中的两大核心要点&#xff1a;栈与堆的内存分配机制&#xff0c;以及…...

windows下查看idea运行的进程占的JVM情况工具

jconsole 查看JVM 查看线程数 自己测试时&#xff0c;可以先不把线程关闭查效果。 也可以用这工具查下是不是有线程一直在增加。...

【新技术】微软 Azure Test Impact Analyzer (TIA) 全面解析

目录 一、什么是 Azure Test Impact Analyzer&#xff1f;二、核心功能与优势三、如何掌握 Azure TIA&#xff1f;四、工作中的典型应用场景五、最佳实践与注意事项六、总结 一、什么是 Azure Test Impact Analyzer&#xff1f; Azure Test Impact Analyzer (TIA) 是微软 Azur…...

JAVA服务内存缓慢上涨,年轻代GC正常但Full GC频繁,如何定位?

1. 分析 &#xff1a; 年轻代GC正常&#xff0c;说明年轻代的对象回收没有问题&#xff0c;可能大部分对象都是朝生夕死的&#xff0c;所以Minor GC能有效清理。但Full GC频繁&#xff0c;通常意味着老年代空间不足&#xff0c;导致频繁进行Full GC来回收老年代。而内存缓慢上…...

浏览器界面无显示,提示“代理服务器可能有问题”,这是怎么回事呢?

前言 &#x1f31f;&#x1f31f;本期讲解浏览器代理服务器解决办法介绍~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1f386;那么废话不…...

C#中的弱引用使用

弱引用&#xff08;Weak Reference&#xff09;是一种特殊的引用类型&#xff0c;它允许你引用一个对象&#xff0c;但不会阻止该对象被垃圾回收器&#xff08;GC&#xff09;回收。弱引用通常用于需要缓存或跟踪对象&#xff0c;但又不希望因保留引用而导致内存泄漏的场景。弱…...

在Linux虚拟机下使用vscode,#include无法跳转问题

总结&#xff1a;需要通过Linux指令来添加编译器和压缩文件&#xff0c;解压&#xff0c;这样获得的编译器会具有可执行权限类似于 -rwxr-xr-x 1 user user 12345 Apr 26 14:22 myscript.sh 如果你直接从window中拖入文件到Linux文件下&#xff0c;你需要自己来再度开启可编译…...

MIL、SIL、HIL与Back-to-Back测试详解:从模型到硬件的完整验证链

1. 引言 在嵌入式系统和控制算法开发中&#xff0c;MIL、SIL、HIL和Back-to-Back测试构成了从模型设计到硬件部署的完整验证流程。它们覆盖不同开发阶段&#xff0c;确保系统功能正确性、实时性和可靠性。 本文将清晰解析这四种测试方法的核心概念、应用场景及差异。 2. 四种测…...

【Android Compose】焦点管理

官方文档链接&#xff1a; https://developer.android.google.cn/develop/ui/compose/touch-input/focus?hlzh-cn 1、更改焦点遍历顺序 1.1、替换一维遍历顺序 &#xff08;1&#xff09;创建焦点引用对象&#xff1a; /// 创建4个引用对象&#xff08;二选一&#xff09…...

启动命令汇总(Redis / Kafka / Flume / Spark)

本文总结了本地开发环境&#xff08;Windows系统&#xff09;中启动推荐系统所需的所有组件命令&#xff0c;包括 Redis、Kafka、Flume 及 SparkStreaming 程序的启动流程。 1. 启动 Redis 进入 Redis 安装目录&#xff0c;执行&#xff1a; redis-server.exe测试连接&#x…...

python 画折线统计图

Python 画折线统计图&#xff08;line chart&#xff09;最常用的是 matplotlib。 最基本的折线图代码如下&#xff1a; import matplotlib.pyplot as plt# 假设这是你的数据 x [1, 2, 3, 4, 5] y [2, 3, 5, 7, 11]# 创建折线图 plt.plot(x, y, markero) # markero 是在点…...

java面向对象编程【高级篇】之继承

目录 &#x1f680;前言&#x1f914;什么是继承&#xff1f;&#x1f31f;权限修饰符&#x1f4af;private 修饰符&#x1f4af;默认&#xff08;无修饰符&#xff09;&#x1f4af;protected 修饰符&#x1f4af;public 修饰符&#x1f4af;归纳 &#x1f99c;继承的特点&…...

【数论分块】数论分块算法模板及真题

1.数论分块的含义 数论分块算法&#xff0c;就是枚举出使得取整函数发生变化的地方。 例如&#xff0c;对表达式 ⌊ n i ⌋ \lfloor \frac{n}{i} \rfloor ⌊in​⌋使用数论分块算法&#xff0c;就可以在 O ( n ) O(\sqrt n) O(n ​)的时间复杂度下枚举所有满足 ⌊ n i − 1 ⌋…...