C++前缀和算法的应用:向下取整数对和 原理源码测试用例

简介: C++前缀和算法的应用:向下取整数对和 原理源码测试用例

本文涉及的基础知识点

C++算法:前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频

题目

向下取整数对和

给你一个整数数组 nums ,请你返回所有下标对 0 <= i, j < nums.length 的 floor(nums[i] / nums[j]) 结果之和。由于答案可能会很大,请你返回答案对109 + 7 取余 的结果。

函数 floor() 返回输入数字的整数部分。

示例

示例 1:

输入:nums = [2,5,9]

输出:10

解释:

floor(2 / 5) = floor(2 / 9) = floor(5 / 9) = 0

floor(2 / 2) = floor(5 / 5) = floor(9 / 9) = 1

floor(5 / 2) = 2

floor(9 / 2) = 4

floor(9 / 5) = 1

我们计算每一个数对商向下取整的结果并求和得到 10 。

示例 2:

输入:nums = [7,7,7,7,7,7,7]

输出:49

#参数范围

1 <= nums.length <= 10^5

1 <= nums[i] <= 10^5

分析

原理

枚举除数和商,然后根据前缀和在O(1)内计算出所有被除数的个数。

时间复杂度

当除数为1,枚举商的复杂度是O(n);当除数为2时,枚举商的复杂度是O(n/2);… 故总复杂度是:n+n/2+n/3…1,越sqrt(n)。故总时间复杂度是O(nsqrt(n))。

细节

为什么要用vNum[i]记录数字i出现的次数。如果不记录,当num是1个10^5和9999个1时,时间复杂度会是O(n*n)。

核心代码

template
class C1097Int
{
public:
C1097Int(long long llData = 0) :m_iData(llData% MOD)
{
}
C1097Int  operator+(const C1097Int& o)const
{
  return C1097Int(((long long)m_iData + o.m_iData) % MOD);
}
C1097Int& operator+=(const C1097Int& o)
{
  m_iData = ((long long)m_iData + o.m_iData) % MOD;
  return *this;
}
C1097Int& operator-=(const C1097Int& o)
{
  m_iData = (m_iData + MOD - o.m_iData) % MOD;
  return *this;
}
C1097Int  operator-(const C1097Int& o)
{
  return C1097Int((m_iData + MOD - o.m_iData) % MOD);
}
C1097Int  operator*(const C1097Int& o)const
{
  return((long long)m_iData * o.m_iData) % MOD;
}
C1097Int& operator*=(const C1097Int& o)
{
  m_iData = ((long long)m_iData * o.m_iData) % MOD;
  return *this;
}
bool operator<(const C1097Int& o)const
{
  return m_iData < o.m_iData;
}
C1097Int pow(long long n)const
{
  C1097Int iRet = 1, iCur = *this;
  while (n)
  {
    if (n & 1)
    {
      iRet *= iCur;
    }
    iCur *= iCur;
    n >>= 1;
  }
  return iRet;
}
C1097Int PowNegative1()const
{
  return pow(MOD - 2);
}
int ToInt()const
{
  return m_iData;
}
private:
int m_iData = 0;;
};
template
int operator+(int iData, const C1097Int& int1097)
{
int iRet = int1097.operator+(C1097Int(iData)).ToInt();
return iRet;
}
template
int& operator+=(int& iData, const C1097Int& int1097)
{
iData = int1097.operator+(C1097Int(iData)).ToInt();
return iData;
}
template
int operator*(int iData, const C1097Int& int1097)
{
int iRet = int1097.operator*(C1097Int<>(iData)).ToInt();
return iRet;
}
template
int& operator*=(int& iData, const C1097Int& int1097)
{
iData = int1097.operator*(C1097Int<>(iData)).ToInt();
return iData;
}
class Solution {
public:
int sumOfFlooredPairs(vector& nums) {
int iMax = std::max_element(nums.begin(), nums.end());
vector vNum(iMax + 1);//vNum[i]记录 ,数字i出现的次数
for (const auto& n : nums)
{
vNum[n]++;
}
vector vSum = { 0 };//vSum[i]表示[0,i)出现的次数
for (const auto& n : vNum)
{
vSum.emplace_back(n + vSum.back());
}
C1097Int<> biRet;
for (int n =1; n <= iMax ; n++ )
{//枚举除数
if (vNum[n] <= 0)
{
continue;//方便调试
}
for (int d = 1; d * n <= iMax; d++)
{//枚举商
//[dn,d*n+n)除以n的结果是d
const int tmp = min(d * n + n, (int)vSum.size()-1);
long long cur = ((long long)vSum[tmp] - vSum[d * n]) * vNum[n]*d;
biRet += C1097Int<>(cur);
}
}
return biRet.ToInt();
}
};

测试用例

template
void Assert(const vector& v1, const vector& v2)
{
if (v1.size() != v2.size())
{
assert(false);
return;
}
for (int i = 0; i < v1.size(); i++)
{
assert(v1[i] == v2[i]);
}
}
template
void Assert(const T& t1, const T& t2)
{
assert(t1 == t2);
}
int main()
{
vector nums = { 2,5,9 };
Solution slu;
auto res =slu.sumOfFlooredPairs(nums);
Assert(10, res);
//CConsole::Out(res);

}

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。

https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程

https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《闻缺陷则喜算法册》doc版

https://download.csdn.net/download/he_zhidan/88348653

鄙人想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
墨家名称的来源:有所得以墨记之。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17

或者 操作系统:win10 开发环境:

VS2022 C++17

相关文章
机器学习/深度学习 算法 自动驾驶
741 0
|
4月前
|
机器学习/深度学习 算法 搜索推荐
从零开始构建图注意力网络:GAT算法原理与数值实现详解
本文详细解析了图注意力网络(GAT)的算法原理和实现过程。GAT通过引入注意力机制解决了图卷积网络(GCN)中所有邻居节点贡献相等的局限性,让模型能够自动学习不同邻居的重要性权重。
671 0
从零开始构建图注意力网络:GAT算法原理与数值实现详解
|
5月前
|
机器学习/深度学习 算法 文件存储
神经架构搜索NAS详解:三种核心算法原理与Python实战代码
神经架构搜索(NAS)正被广泛应用于大模型及语言/视觉模型设计,如LangVision-LoRA-NAS、Jet-Nemotron等。本文回顾NAS核心技术,解析其自动化设计原理,探讨强化学习、进化算法与梯度方法的应用与差异,揭示NAS在大模型时代的潜力与挑战。
1232 6
神经架构搜索NAS详解:三种核心算法原理与Python实战代码
|
5月前
|
传感器 算法 定位技术
KF,EKF,IEKF 算法的基本原理并构建推导出四轮前驱自主移动机器人的运动学模型和观测模型(Matlab代码实现)
KF,EKF,IEKF 算法的基本原理并构建推导出四轮前驱自主移动机器人的运动学模型和观测模型(Matlab代码实现)
164 2
|
5月前
|
算法
离散粒子群算法(DPSO)的原理与MATLAB实现
离散粒子群算法(DPSO)的原理与MATLAB实现
237 0
|
6月前
|
机器学习/深度学习 人工智能 编解码
AI视觉新突破:多角度理解3D世界的算法原理全解析
多视角条件扩散算法通过多张图片输入生成高质量3D模型,克服了单图建模背面细节缺失的问题。该技术模拟人类多角度观察方式,结合跨视图注意力机制与一致性损失优化,大幅提升几何精度与纹理保真度,成为AI 3D生成的重要突破。
562 0
|
6月前
|
算法 区块链 数据安全/隐私保护
加密算法:深度解析Ed25519原理
在 Solana 开发过程中,我一直对 Ed25519 加密算法 如何生成公钥、签名以及验证签名的机制感到困惑。为了弄清这一点,我查阅了大量相关资料,终于对其流程有了更清晰的理解。在此记录实现过程,方便日后查阅。
705 1
|
7月前
|
Java 测试技术 容器
Jmeter工具使用:HTTP接口性能测试实战
希望这篇文章能够帮助你初步理解如何使用JMeter进行HTTP接口性能测试,有兴趣的话,你可以研究更多关于JMeter的内容。记住,只有理解并掌握了这些工具,你才能充分利用它们发挥其应有的价值。+
1098 23
|
9月前
|
SQL 安全 测试技术
2025接口测试全攻略:高并发、安全防护与六大工具实战指南
本文探讨高并发稳定性验证、安全防护实战及六大工具(Postman、RunnerGo、Apipost、JMeter、SoapUI、Fiddler)选型指南,助力构建未来接口测试体系。接口测试旨在验证数据传输、参数合法性、错误处理能力及性能安全性,其重要性体现在早期发现问题、保障系统稳定和支撑持续集成。常用方法包括功能、性能、安全性及兼容性测试,典型场景涵盖前后端分离开发、第三方服务集成与数据一致性检查。选择合适的工具需综合考虑需求与团队协作等因素。
1367 24
|
9月前
|
SQL 测试技术
除了postman还有什么接口测试工具
最好还是使用国内的接口测试软件,其实国内替换postman的软件有很多,这里我推荐使用yunedit-post这款接口测试工具来代替postman,因为它除了接口测试功能外,在动态参数的支持、后置处理执行sql语句等支持方面做得比较好。而且还有接口分享功能,可以生成接口文档给团队在线浏览。
388 2

热门文章

最新文章