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

如何降低程序的时间复杂度,提高运行时效?

如何提高运行时效,解决程序运行太慢问题

  • 引言
  • 今天,我们深入剖析一个典型的多测试用例算法题目:
    • 约束与挑战
      • 优化关键:
    • 代码实现
  • 结论

引言

在信息爆炸的时代,人们需要更快速、更简洁地传递信息。网络语言缩写(如“OMG”代表“Oh my God”)正好满足了这一需求,它让复杂的表达浓缩成简短符号,提升了沟通效率。作为算法工程师,我总是被这种“精炼”精神启发:在编程中,如何用最少的代码解决最复杂的问题?

今天,我们深入剖析一个典型的多测试用例算法题目:

  • 给定长度为 nnn 的数组 aaa,以及 qqq 个查询,每个查询提供 xxxyyy,找出满足 ai+aj=xa_i + a_j = xai+aj=xai⋅aj=ya_i \cdot a_j = yaiaj=y 的数对 (i,j)(i, j)(i,j)1≤i<j≤n1 \leq i < j \leq n1i<jn)的数量。该题目涉及多组测试,约束严格(∑n,∑q≤2×105\sum n, \sum q \leq 2 \times 10^5n,q2×105),考验高效数据结构和数学优化的结合。
    这个问题的核心在于避免 O(n2)O(n^2)O(n2) 暴力枚举,通过二次方程根求解转化为 O(1)O(1)O(1) 查询。提供的 C++ 代码框架优秀,但存在浮点精度问题(sqrt 对大整数不精确),我会基于它进行优化,提供完整可运行版本。下面,从问题分析、数学推导,到代码实现,一步步拆解。
    问题分析
    问题描述

  • 输入:
    第一行:整数 ttt(测试用例数,1≤t≤1041 \leq t \leq 10^41t104)。
    每个测试用例:
    第一行:整数 nnn1≤n≤2×1051 \leq n \leq 2 \times 10^51n2×105)。
    第二行:nnn 个整数 a1,…,ana_1, \dots, a_na1,,an∣ai∣≤109|a_i| \leq 10^9ai109)。
    第三行:整数 qqq1≤q≤2×1051 \leq q \leq 2 \times 10^51q2×105)。
    接下来 qqq 行:每个两个整数 x,yx, yx,y∣x∣≤2×109|x| \leq 2 \times 10^9x2×109∣y∣≤1018|y| \leq 10^{18}y1018)。

  • 保证 ∑n≤2×105\sum n \leq 2 \times 10^5n2×105∑q≤2×105\sum q \leq 2 \times 10^5q2×105

  • 输出:每个测试用例,对于 qqq 个查询,每行输出一个答案(数对数量)。
    示例(单测试用例简化):
    n=3n=3n=3,数组 [1,3,2][1, 3, 2][1,3,2]q=1q=1q=1,查询 x=3,y=2x=3, y=2x=3,y=2
    分析:
    i=1,j=2i=1, j=2i=1,j=2: 1+3=4≠31+3=4 \neq 31+3=4=31×3=3≠21 \times 3=3 \neq 21×3=3=2
    i=1,j=3i=1, j=3i=1,j=3: 1+2=3=31+2=3 = 31+2=3=31×2=2=21 \times 2=2 = 21×2=2=2(满足)。
    i=2,j=3i=2, j=3i=2,j=3: 3+2=5≠33+2=5 \neq 33+2=5=33×2=6≠23 \times 2=6 \neq 23×2=6=2

  • 答案:1

约束与挑战

  • 多测试用例:需循环处理,但总规模 O(∑n+∑q)O(\sum n + \sum q)O(n+q)
    大范围:aia_iai 可负,x2−4yx^2 - 4yx24y 可达 ±8×1018\pm 8 \times 10^{18}±8×1018,需 64 位整数(long long)。
    重复元素:需频率计数,处理组合 (f2)\binom{f}{2}(2f)
    挑战:判别式 d=x2−4yd = x^2 - 4yd=x24y 求整数平方根,避免浮点误差(double 精度仅至 101510^{15}1015)。
    时间要求:总 O((∑n+∑q)log⁡n)O((\sum n + \sum q) \log n)O((n+q)logn) 可接受,使用 map 或 unordered_map。

  • 为什么这个题目有趣?
    它将代数(二次方程)与数据结构(哈希计数)融合,体现了“缩写”般的算法美学:从海量数据中“浓缩”答案。实际场景如大数据匹配、密码学中的因式分解优化。
    数学推导:从方程到根求解
    给定 ai+aj=xa_i + a_j = xai+aj=xai⋅aj=ya_i \cdot a_j = yaiaj=y,则 ai,aja_i, a_jai,aj 为方程 t2−xt+y=0t^2 - x t + y = 0t2xt+y=0 的根。

  • 判别式:d=x2−4yd = x^2 - 4yd=x24y
    d<0d < 0d<0,无实根,答案 0。
    d=0d = 0d=0,双根 r=x/2r = x / 2r=x/2。若 xxx 偶数且 rrr 在数组中出现 fff 次,答案 f(f−1)2\frac{f(f-1)}{2}2f(f1)
    d>0d > 0d>0,根 r1=x+d2r_1 = \frac{x + \sqrt{d}}{2}r1=2x+dr2=x−d2r_2 = \frac{x - \sqrt{d}}{2}r2=2xd
    d\sqrt{d}d 须为整数(完美平方),且 x+dx + \sqrt{d}x+d 偶数(确保 r1,r2r_1, r_2r1,r2 整数)。
    r1=r2r_1 = r_2r1=r2,同上;否则,答案 f1×f2f_1 \times f_2f1×f2

优化关键:

  • 预处理:用 map<long long, long long> 统计频率(支持负键)。
    查询:计算 ddd,用整数二分求 d\sqrt{d}d(避免浮点)。
    验证:r1+r2=xr_1 + r_2 = xr1+r2=xr1×r2=yr_1 \times r_2 = yr1×r2=y(虽理论成立,但防计算误差)。

此法每个查询 O(log⁡109)O(\log 10^9)O(log109)(二分求 sqrt),总时间 O((∑n+∑q)log⁡n)O((\sum n + \sum q) \log n)O((n+q)logn),高效。
解决方案设计
整体框架

  • 预处理:每个测试用例清空 map,读 nnnaia_iai,计数频率 O(nlog⁡n)O(n \log n)O(nlogn)
    查询处理:读 qqq,对每个:
    计算 d=x∗x−4∗yd = x*x - 4*yd=xx4y(注意符号)。
    d<0d < 0d<0,输出 0。
    二分求 sd=⌊d⌋sd = \lfloor \sqrt{d} \rfloorsd=d,检查 sd×sd==dsd \times sd == dsd×sd==d
    (x+sd)%2==0(x + sd) \% 2 == 0(x+sd)%2==0,计算 r1=(x+sd)/2r_1 = (x + sd)/2r1=(x+sd)/2r2=(x−sd)/2r_2 = (x - sd)/2r2=(xsd)/2
    根据 r1==r2r_1 == r_2r1==r2 计算组合数。

  • 边界处理:
    d=0d = 0d=0: 特殊处理 sd=0sd = 0sd=0
    ddd: 跳过。
    溢出:C++ long long 乘法安全(2×109×2×109=4×1018<9×10182 \times 10^9 \times 2 \times 10^9 = 4 \times 10^{18} < 9 \times 10^{18}2×109×2×109=4×1018<9×1018)。
    map vs unordered_map:map 稳定,支持负键;unordered_map 更快但需哈希。

时间与空间复杂度

  • 时间:预处理 O(∑nlog⁡n)O(\sum n \log n)O(nlogn),查询 O(∑qlog⁡109)≈O(2×105×30)=6×106O(\sum q \log 10^9) \approx O(2 \times 10^5 \times 30) = 6 \times 10^6O(qlog109)O(2×105×30)=6×106,优秀。
    空间:O(∑n)O(\sum n)O(n),最坏 2×1052 \times 10^52×105

潜在扩展

  • aia_iai 非整数:退化为近似匹配,复杂度飙升。
    分布式:用 Redis 存频率。

代码实现

  • 基于提供的代码框架,我优化了 sqrt 计算:引入整数二分求完美平方根,避免浮点误差。同时,添加 ios_base::sync_with_stdio(false) 加速 I/O,处理多测试用例。完整代码如下(使用 map 确保稳定性):
#include <bits/stdc++.h>
using namespace std;long long integer_sqrt(long long n) {if (n < 0) return -1;if (n == 0) return 0;long long l = 1, r = min(n, 3000000000LL); // sqrt(8e18) ~ 2.8e9while (l <= r) {long long m = l + (r - l) / 2;if (m <= n / m) {l = m + 1;} else {r = m - 1;}}return r; // floor(sqrt(n))
}int main() {ios_base::sync_with_stdio(false);cin.tie(NULL);int t;cin >> t;while (t--) {int n;cin >> n;map<long long, long long> cnt;for (int i = 0; i < n; i++) {long long number;cin >> number;cnt[number]++;}long long q;cin >> q;while (q--) {long long x, y, res = 0;cin >> x >> y;long long d = x * x - 4 * y;if (d < 0) {cout << 0 << '\n';continue;}long long sd = integer_sqrt(d);if (sd * sd != d) {cout << 0 << '\n';continue;}if ((x + sd) % 2 == 0) {long long r1 = (x + sd) / 2;long long r2 = (x - sd) / 2;if (r1 == r2) {res = cnt[r1] * (cnt[r1] - 1) / 2;} else {res = cnt[r1] * cnt[r2];}}cout << res << '\n';}}return 0;
}

代码解释

integer_sqrt:二分求 ⌊n⌋\lfloor \sqrt{n} \rfloorn,时间 O(log⁡109)O(\log 10^9)O(log109)。边界 r=3×109r = 3 \times 10^9r=3×109 覆盖最大 ddd
精确检查:sd * sd != d 过滤非完美平方(乘法安全,无溢出)。
I/O 优化:cin.tie(NULL) 加速大输入。
验证省略:数学上 r1,r2r_1, r_2r1,r2 必满足原方程,但可加 if(r1 + r2 != x || r1 * r2 != y) res=0; 增强鲁棒。
测试:对于示例输入(t=1, n=3, a=[1,3,2], q=1, x=3 y=2),输出 1。适用于大 dddx=2×109,y=0x=2 \times 10^9, y=0x=2×109,y=0d=4×1018d=4 \times 10^{18}d=4×1018,sd=2e9。

结论

  • 计算机的一切都是人赋予的,别人能做的事情,我也可以!没有天赋,就一直重复!
http://www.dtcms.com/a/610122.html

相关文章:

  • openEuler系统下sudo权限配置与使用指南
  • 一个网站好不好做网站赔钱了
  • 受欢迎的丹阳网站建设有哪些调查网站可以做兼职
  • 品牌型网站成功案例图片网站建设的流程分析
  • 手机网站用什么域名潍坊网站建设 世纪环球16楼
  • 17、grafana安装
  • 2025年蚌埠市“三首产品”、市级服务型制造示范、市级企业技术中心等5个项目认定申报指南大全
  • 做一个个人主页的网站怎么做房地产销售段子
  • 个人网站定制国内免费的短视频素材网站
  • 1999-2023年 微观企业劳动生产率数据
  • 二手书店网站建设规划书网站域名 过期
  • 选择Rust的理由:从内存管理到抛弃抽象
  • JUC包里的同步组件主要实现了AQS的哪些主要方法
  • wordpress公司展示网站模板网站推广需要多少钱易下拉系统
  • wordpress站点费用网站底部的图标
  • 引力本体的几何之歌:从星体永恒吸引到人工场操控时空的范式革命
  • Docker-Android容器化开发:如何通过Cpolar实现远程环境无缝协作
  • ## 2.2 状态同步
  • 翻译技巧英语
  • 11.14 脚本网页 迷宫逃离
  • 手机网站开发成appWordPress博客建站系统
  • 定义舱驾一体新架构:黑芝麻智能武当C1200家族如何成为跨域计算“第一芯”
  • 小白建站东莞网络营销公司
  • SImpack轨道车辆建模练习
  • react项目创建从0到1及安装(ts、axios、路由、redux)
  • 网站怎么做动态背景图片做网站需要准备哪些材料
  • 网站建设分哪几个版块关键词没有排名的网站怎么做
  • 什么是关键字驱动测试(Keyword-Driven Testing)?
  • 颠覆叙事:Google Veo 3.1与Flow如何开启连贯AI动画长视频时代
  • 【运维】Nginx 入门笔记