C++拾趣——使用stl标准库生成等差、等比数列的方法

蓝桥杯2019年第十届 c/c++ c组 第九题 等差数列(满分代码) 蓝桥杯2019年第十届 c/c++ c组 第九题 等差数列(满分代码) 题目: 输入n,接下来输入n个数据,求最小数据到最大数据之间(包括)满足等差的数最少是多少个 输出符合等差的数的个数 代码: #include <iostream> using namespace std; int arr[1000001]; void Swap(int arr[], int a, int d) ... 阅读详情
AI摘要

本文介绍使用C++ STL库中的iota、generate、partial_sum等函数简化等差数列、等比数列及斐波那契数列的生成。同时展示了如何利用accumulate、adjacent_difference等函数精简累加、累乘及序列比较等操作。

        代码是思想的表达。阅读代码是一个猜测、求证的过程。这个过程非常费脑,所以人们都不喜欢啰啰嗦嗦的表达方式。于是在相同认知水平下,简洁高效的表达是喜闻乐见的。本文将抛砖引玉,通过一些案例讲解如何去简化代码。(转载请指明出于breaksoftware的csdn博客)

关系数列

等差数列

        比如我们要构建的序列存储的值是0,1,2,3,4……9999。

常规写法

        使用for循环

std::vector<int> vec;
for (int i = 0; i < 10000; i++) {
    vec.push_back(i);
}

简洁写法

iota

        使用std标准库的iota。

std::vector<int> vec(10);
std::iota(vec.begin(), vec.end(), 0);

generate

        使用std标准库的generate

    std::vector<int> vec(10);
    std::generate(vec.begin(), vec.end(), [] {static int i = 0; return i++;});

        或者

    std::vector<int> vec(10);
    std::generate(vec.begin(), vec.end(), [n = 0]() mutable {return n++;});

partial_sum

        使用std标准库的partial_sum,代码量减少了一半。 partial是局部、区间的意思,sum是累加的意思。第1、2个参数是需要被计算的容器起止迭代器,第3个参数是计算结果保存的起始迭代器。它还有第4个参数,用于描述怎么计算的。

std::vector<int> vec(10000, 1);
vec[0] = 0;
std::partial_sum(vec.begin(), vec.end(), vec.begin());

        std::partial_sum方法对区间数据进行累加。具体的计算规则是

template< class InputIt, class OutputIt >
OutputIt partial_sum( InputIt first, InputIt last, OutputIt d_first );
// *(d_first)   = *first;
// *(d_first+1) = *first + *(first+1);
// *(d_first+2) = *first + *(first+1) + *(first+2);
// *(d_first+3) = *first + *(first+1) + *(first+2) + *(first+3);
// ...

        上述方法有个缺点,就是需要填充10000个1之后再计算。我们可以稍微修改如下,效率会好些。

std::vector<int> vec(10000);
vec[0] = 0;
std::partial_sum(vec.begin(), vec.end(), vec.begin(), [](const int&a, int b) {return a + 1;});

        如果要生成9999,9998……0这样递减的数列,则可以把第一个元素赋值为9999后,传递一个减法lambda表达式

std::vector<int> vec(10000);
vec[0] = 9999;
std::partial_sum(vec.begin(), vec.end(), vec.begin(), [](const int& a, int b) {return a - 1;} );

等比数列

        比如我们要生成1,2,4,8,16……这样2倍关系的数列。

常规写法

std::vector<int> vec;
for (int i = 0; i < 10; i++) {
    vec.push_back(pow(2, i));
}

精简写法

 generate

    std::vector<int> vec(10);
    std::generate(vec.begin(), vec.end(), [] {static int i = 0; return pow(2, i++);});

        或者

    std::vector<int> vec(10);
    std::generate(vec.begin(), vec.end(), [n = 0]() mutable {return pow(2, n++);});

partial_sum

std::vector<int> vec(10, 2);
vec[0] = 1;
std::partial_sum(vec.begin(), vec.end(), vec.begin(), std::multiplies<int>());

        使用比值2初始化vector容器,然后给partial_sum传递乘法函数对象。

        或者使用lambda表达式

std::vector<int> vec(10);
vec[0] = 1;
std::partial_sum(vec.begin(), vec.end(), vec.begin(), [](const int& x, int y) {return x * 2;});

        如果要生成512,256……2,1这样的等比数列,则可以把容器的第一个元素设置为1024,然后给partial_sum传递除法函数对象。

std::vector<int> vec(10, 2);
vec[0] = 512;
std::partial_sum(vec.begin(), vec.end(), vec.begin(), std::divides<int>());

        或者使用lambda表达式

std::vector<int> vec(10);
vec[0] = 512;
std::partial_sum(vec.begin(), vec.end(), vec.begin(), [](const int& x, int y) {return x / 2;});

斐波那契数列

常规写法

std::vector<int> vec(10);
vec[0] = 1;
for (auto it = std::next(vec.begin()); it != vec.end(); it++) {
    auto it_prev = std::prev(it);
    if (vec.begin() != it_prev) {
        *it = *it_prev + *std::prev(it_prev);
    }
    else {
        *it = *it_prev;
    }  
}

精简写法

std::vector<int> vec(10);
vec[0] = 1;
std::adjacent_difference(vec.begin(), std::prev(vec.end()), std::next(vec.begin()), std::plus<int>());

        adjacent_difference用于计算前后两个数据的差。第4个参数的默认操作是减法,其计算规则如下

template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 >
ForwardIt2 adjacent_difference( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first );
// *(d_first)   = *first;
// *(d_first+1) = *(first+1) - *(first);
// *(d_first+2) = *(first+2) - *(first+1);
// *(d_first+3) = *(first+3) - *(first+2);
// ...

累计型操作

        比较常见的累计型操作如累加、累乘

累加

常规写法

std::vector<int> vec = { 16, 8, 4 };
int sum = 0;
for (int n : vec) {
    sum += n;
}

精简写法

std::vector<int> vec = { 16, 8, 4 };
int sum = std::accumulate(vec.begin(), vec.end(), 0);

        代码也减少一半。

        accumulate第1、2个参数是需要计算的容器的起止迭代器,第3个参数是初始计算的值。它还有第4个参数,用于描述如何累计。默认是累加操作。

        我们再看个累乘操作。

std::vector<int> vec = { 16, 8, 4 };
int product = std::accumulate(vec.begin(), vec.end(), 1, std::multiplies<int>());

组合成一个字符串

常规写法

std::vector<int> vec = { 16, 8, 4 };
std::string str;
for (int n : vec) {
    if (!str.empty()) {
        str.append(",");
    }
    str.append(std::to_string(n));
}

精简写法

std::string s = std::accumulate(std::next(vec.begin()), vec.end(),
    std::to_string(vec[0]), // start with first element
    [](std::string a, int b) { return a + ',' + std::to_string(b);}
);

序列比较

两个序列中,相同偏移的元素值相等的个数

常规写法

std::vector<int> a = { 1, 2, 3, 4, 5 };
std::vector<int> b = { 5, 4, 3, 2, 1 };
int num = 0;
auto it_a = a.begin();
auto it_b = b.begin();
for (; it_a != a.end() && it_b != b.end(); it_a++, it_b++) {
    if (*it_a == *it_b) {
        num++;
    }
}

精简写法

std::vector<int> a = { 1, 2, 3, 4, 5 };
std::vector<int> b = { 5, 4, 3, 2, 1 };
int num = std::inner_product(a.begin(), a.end(), b.begin(), 0, std::plus<>(), std::equal_to<>());

        inner_product方法对两个序列中相同位置的元素使用第5个参数指向的函数对象计算,计算的结果通过第4个参数指向的函数对象进行再计算。即

template<class InputIt1, class InputIt2, class T,
         class BinaryOperation1, class BinaryOperation2> 
T inner_product( InputIt1 first1, InputIt1 last1,
                 InputIt2 first2, T init,
                 BinaryOperation1 op1,
                 BinaryOperation2 op2 );
// 以初值 init 初始化积累器 acc ,然后
// 以表达式 acc = op1(acc, op2(*first1, *first2)) 修改它,再以表达式acc = op1(acc, op2(*(first1+1), *(first2+1))) 修改它,以此类推

两个序列元素是否完全一致(顺序无关)

        比如一个序列a是1,2,3;序列b是2,1,3;序列c是1,2,1。则a和b中元素完全一致,只是顺序不一致;而c和a、b中元素不一致。可以想象这个算法不是简简单单就能写出来的。我们直接看精简写法

精简写法

std::vector<int> v1{ 1,1,2,2,5 };
std::vector<int> v2{ 5,1,2,1,2 };
bool permutation = std::is_permutation(v1.begin(), v1.end(), v2.begin(), v2.end());

        is_permutation用于判断两个序列是否是同一个序列的不同(或相同)顺序排列。

(个人C++学习笔记)使用C++ STL标准模板库Vector容器写的等差数列计算器 ** 使用C++ STL标准模板库Vector容器写的等差数列计算器 //个人学习笔记有兴趣的可以翻阅 #include &lt;iostream&gt; #include &lt;vector&gt; #include &lt;windows.h&gt; using namespace std; vector&lt;int&gt; opnumber(100);//新建一个int类型的Vect... 阅读详情

相关推荐

C++ STL四大生成算法:accumulate、fill、generate、iota实战精讲

STL算法中的数据生成与聚合操作,是C++工程实践中提升代码可读性、解耦逻辑与容器的关键能力。其核心原理在于将‘数据如何产生’(generate/iota/fill)和‘数据如何合并’(accumulate)从遍历循环中抽象出来,形成高内聚、低耦合的函数式编程范式。这类操作具备显著的技术价值:避免手写易错循环、支持编译器深度优化、天然适配并行化,并在嵌入式校准、日志聚合、间接排序等真实场景中发挥不可替代作用。本文聚焦accumulate折叠聚合、fill批量赋值、generate定制生成与iota序列构造四

diaohong5075的博客 496

C++ 合辑——等差数列

等差数列:是指一组数字中,相邻的数字之间的差值相等; 例如: 1 2 3 4 5…. 这组数字,相邻的两数之间相差1; 1 3 5 7 9…. 这组数字,相邻的两数之间相差2;

weixin_46692659的博客 7075

C++ vector初始化方法详解:从基础语法到性能优化实战

在C++标准模板库(STL)中,容器是管理数据集合的核心组件,其初始化方式直接影响程序的正确性与执行效率。vector作为最常用的动态数组容器,其底层基于连续内存分配与自动扩容机制,理解其初始化原理对编写高性能代码至关重要。从工程实践角度看,不同的初始化方法在内存分配策略、元素构造次数上存在显著差异,不当使用会导致不必要的拷贝开销与内存重分配,成为性能瓶颈。本文聚焦于vector初始化的多种技术方案,涵盖默认构造、列表初始化、迭代器范围构造及C++11/17新特性,并结合emplace_back原位构造、r

weixin_30613343的博客 406

C++ 求 等差数列

输入三个整数,之间用空格隔开。第1个数作为首项,第2个数作为末项,第3个位公差。

2301_76989860的博客 1470

GESP C++四级最长连续段解题:排序算法与调试技巧全解析

在算法与数据结构的学习中,排序是基础且核心的操作,它通过将无序数据按特定规则排列,为后续处理提供便利。其原理基于比较或非比较策略,旨在提升数据访问与处理的效率。掌握排序算法不仅有助于理解时间复杂度与空间复杂度的权衡,更是解决众多实际问题的关键技术。在编程竞赛和等级认证中,排序常与去重、遍历等操作结合,用于解决如寻找最长连续序列这类经典问题。本文以GESP C++四级考试为背景,深入探讨如何运用排序法高效求解“最长连续段”问题,并分享实用的调试技巧与备考策略,帮助考生巩固基础,提升实战能力。

weixin_30664615的博客 435

C++程序计算等差数列的第N项

首先,让我们了解一下等差数列的定义和公式。一个等差数列可以表示为:a,a + d,a + 2d,a + 3d,…,其中a是首项,d是公差(每一项与前一项之间的差值)。现在,您可以运行这段C++代码,并根据您的输入获取等差数列的第N项。这个程序可以很方便地计算等差数列的任意一项,只需要输入对应的首项、公差和项数即可。来获取用户输入的首项、公差和要计算的项数。接下来,我们使用上面提到的等差数列的公式。现在我们来编写一个C++程序,计算等差数列的第N项。,分别用于存储等差数列的首项、公差和要计算的项数。

JfBackend的博客 658

C++_chapter8_STL算法

算法就是全局的函数,每个容器有自己的成员函数,而算法就是全局函数。容器要想使用算法,通过迭代器给算法传递位置。而传递是前闭后开的区间,因为不包含最后一个位置。判断空区间:beginiter = enditer.所以,算法是搭配迭代器使用的全局函数。

weixin_43916755的博客 1071

EC20模块实战:5步搞定MQTT连接阿里云IoT(附常见错误排查)

本文详细介绍了使用EC20 4G模块通过AT指令连接阿里云IoT平台的完整实战流程。文章以智能农业项目为背景,从硬件接线、网络注册、PDP激活,到MQTT连接配置、一型一密动态注册及数据收发,提供了清晰的5步操作指南,并重点附上了常见错误排查方法,帮助开发者快速实现稳定可靠的物联网设备上云。

weixin_29209801的博客 196

【C++】C++ STL string 详解

本文详细介绍了C++ STL中的string类及其底层实现。主要内容包括:1) STL的六大组件(容器、算法、迭代器等)及其关系;2) string类的本质是字符数组,相比C字符串具有自动扩容等优势;3) string的历史渊源,它早于STL出现且接口设计存在冗余;4) string实际上是basic_string<char>的别名,支持不同字符编码类型;5) 深入解析ASCII、Unicode(UTF-8/16/32)和GBK等编码方案的区别,以及UTF-8兼容ASCII的特性。文章还比较了Windows

feng_qi0325的博客 415

CESM笔记——CESM1.0-CESM1.2.2-CESM2.1.3三个版本模式工作流对比

最近测试了CESM1.0,CESM1.2.2和CESM2.1.3三个版本,不同版本在workflow上有一些区别,来做点笔记。 CESM1.0 测试compset:B_2000,F_2000 workflow: 1. create_newcase -case ~/CESM/cesm1_0/script/B_2000 -compset B_2000 -res f19_g16 -mach tianhe 2. cd B_2000 (optional) env_mach_pes.xml ##修改核数,

砍柴姑娘Jourosy的博客 4942

TIMER-XL:突破长上下文限制的Transformer时序预测新范式

本文深入解析了清华大学提出的TIMER-XL模型,这是一种突破长上下文限制的Transformer时序预测新范式。它采用Decoder-only架构与补丁级生成技术,并创新性地引入TimeAttention机制,有效解决了传统模型在处理海量历史数据时面临的“上下文瓶颈”问题,显著提升了长序列预测的精度与稳定性。

weixin_28340315的博客 445

C++ 使用分治减小模板递归深度

我们知道有个排序算法叫归并排序,将长列表不断拆分成最小单元后合并。

PWjBgLubj的博客 192

基于微信小程序的扫码签到系统源码

大等于jdk1.8,大于mysql5.5,idea(eclipse),微信开发者工具。代码注释齐全,没有多余代码,适合学习(毕设),二次开发,包含论文技术相关文档。签到管理:新增签到,点击查看码展示二维码(有时效性)springboot mybatis 小程序。签到管理:查看用户创建的签到,可删除。用户管理:查看注册用户信息,及删除。签到记录:查看用户签到记录:可删除。个人信息:展示个人信息,可修改。统计分析:查看用户,签到数量。签到记录:查看用户签到记录。登录注册(含授权登录)我的签到:查看签到记录。

wfuhui的博客 5224

C++ std::iota:从手动循环到高效序列生成的现代实践

在C++编程中,序列生成是基础且常见的操作,其核心原理是通过迭代和赋值构建有序数据集合。传统方法如手动循环或std::generate虽能实现,但在代码简洁性和意图明确性上存在局限。C++标准库提供的std::iota算法,专门用于生成连续递增的序列,通过前置递增运算符(++)实现高效填充,提升了代码的可读性和STL风格的一致性。该技术在需要生成索引、ID或等差数列的场景下具有显著价值,例如在并行计算中分配任务ID,或结合std::sort实现间接排序以处理大对象集合。本文以std::iota为例,深入解析

weixin_34335458的博客 302

求无向图中所有的环 C++ python

求无向图中所有的环

random_repick的专栏 1151

实战演练:基于Veristand Custom Device的硬件在环(HIL)数据流控制模块开发

本文详细介绍了基于Veristand Custom Device的硬件在环(HIL)数据流控制模块开发实战。通过LabVIEW环境配置、动态路由逻辑构建、实时处理核心开发及性能优化等关键步骤,帮助工程师快速掌握定制化HIL测试系统的开发技巧,提升测试效率与准确性。

weixin_29206669的博客 475

C++ STL vector模拟实现:从动态数组到迭代器失效的深度解析

动态数组是计算机科学中基础且高效的数据结构,它通过在连续内存中存储元素,实现了O(1)时间的随机访问。其核心原理在于通过动态内存管理实现容量的自动扩展,通常采用几何倍率(如1.5或2倍)扩容策略,将多次扩容的拷贝成本均摊,从而在尾部操作上达到均摊O(1)的时间复杂度,这是其高性能的关键。这一技术价值在于为算法提供了灵活且高速的线性存储支持。在C++标准模板库(STL)中,`std::vector`正是这一思想的经典实现,它广泛应用于需要高效随机访问和尾部操作的场景,如数据缓冲区、动态集合存储等。理解其底层机

weixin_32183107的博客 309

[Dify实战] OA 公文排版助手:自动格式化、编号、生成摘要-带配套资源

摘要: Dify 公文排版助手通过自动化解决公文处理中的格式混乱、编号错漏等问题。支持标题层级自动编号、摘要生成、要素补全等功能,输出标准化Markdown格式。核心流程包括输入原文、智能识别、自动排版与要素输出,适用于通知、纪要等场景。实施需统一模板规则,规范输入格式,并通过试跑优化纠错率与处理效率。关键价值在于减少人工返工,提升排版一致性,未来可对接OA系统实现全流程自动化。

技术小甜甜:传播可落地技术,帮助个人和企业降低解决真实场景问题的成本 470

C++ iota()函数实践

C++ iota()函数实践

YMWM_的博客 1157

从零开始学习CANoe(六)—— CAPL 测试节点

创建CAPL Test Module的两种方式

蚂蚁小兵 1万+

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

C++ vector初始化:从for循环到std::iota的优雅实践

在C++编程中,容器初始化是基础且关键的操作,它直接影响代码的性能和可读性。std::vector作为最常用的动态数组容器,其初始化方式的选择体现了开发者对标准库的掌握程度。从内存管理的原理来看,不当的初始化会导致不必要的内存重新分配和性能开销。现代C++提倡使用标准库算法替代手写循环,这不仅提升了代码的简洁性,还能借助编译器的优化获得更好的执行效率。std::iota算法正是这一理念的典范,它能高效、清晰地生成连续数值序列。在实际工程中,结合reserve进行内存预分配,可以避免动态增长带来的成本。这些技

455

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

等差数列连续异或模板

网上找的模板,还不太懂,改了下,先留着 #include &lt;cstdio&gt; #include &lt;ctime&gt; #include &lt;cstdlib&gt; #include &lt;cstring&gt; #include &lt;queue&gt; #include &lt;string&gt; #include &lt;set&gt; #include &am

445822357 229

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

别光抄答案!用东方博宜OJ的10道经典题,带你吃透C++竞赛常用技巧

本文通过东方博宜OJ平台的10道经典题目,深入解析C++竞赛编程中的优化技巧。从基础题目的隐藏优化点到算法选择与时间复杂度优化,再到STL的高效应用和代码风格调试技巧,全方位提升编程水平。特别适合希望通过OJ题库精进C++竞赛技能的学习者。

weixin_33695450的博客 582

LeetCode.2612最少翻转次数C++

假设下标i经过一次翻转后的下标为j,这个下标j肯定不是一个特定的下标,它代表翻转后的所有可能的下标。i>n-k的情况,当子数组在整个数组的最右边时,L=n-k,R=n-1。翻转后的下标为j=L+R-i=2*n-k-i-1。例如 对于k=4,长度为4的子数组,右端点最小是k-1=3,当i=0,1,2,i不可能是数组的右端点;i<k-1的情况,当子数组在整个数组的最左边时,L=0,R=k-1。i位置经过一次翻转后的下标为j,将i和j看成是用一条边连接,这条边的边权为1,代表翻转次数。也可以右移L-1,R-1。

tomatop的博客 19

cs研究生面试机试题(持续更新)

筛选了各学校的难度较低和考点频率较高的机试题目,注意高校机考时,大多数高校的机考系统不同于Leetcode, 需要自己写输入输出(参考ACM模式),每道题目备注了题目出处,当然可能多个学校考察过。和前一道题类似,使用STL,将数字和字符单独存在string中,这里判断是不是数字使用cctype的isdigit()函数。思路:循环遍历所有的四位数,将int型的数反转转为string后在转回int,得到其反序数,再判断是否是9倍关系。解题关键是如何获取其后的第三个字母,这里需要熟练记住,当成一个模版直接用。

2301_80162458的博客 351

C++内存管理底层探秘:从malloc原理到内存池优化实战

内存管理是计算机科学的核心基础概念,它负责程序运行时内存资源的分配与回收。其原理涉及操作系统虚拟内存机制、分配器算法(如空闲链表、伙伴系统)以及硬件MMU的协同工作。理解内存管理机制的技术价值在于能够编写出高性能、低延迟且稳定的系统软件,尤其在游戏开发、高频交易、嵌入式系统等对资源极度敏感的应用场景中至关重要。本文以C++为背景,深入剖析Glibc的ptmalloc等通用内存分配器的底层实现,并探讨如何通过定制内存池和选择高效分配器(如tcmalloc、jemalloc)来解决内存碎片和多线程性能瓶颈等实际

chuchen7021的博客 388
上一篇: C++拾趣——STL容器的插入、删除、遍历和查找操作性能对比(Windows Visual Studio)——遍历和删除
下一篇: C++拾趣——使用stl标准库实现排序算法及评测
breaksoftware
breaksoftware 领域专家: 操作系统技术领域 领域专家: 操作系统技术领域
博客等级 码龄20年 6901粉丝 724原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

breaksoftware

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值