算法分析-第1关:双关系递推数列

任务描述

本关任务:运用枚举和递推的基本思想,通过编程计算出双关系递推数列。设集合 M 定义如下:

1.初始 1∈M;

2.若x∈M,则有2x+1∈M,5x−1∈M;

3.再无其它的数属于M。

试求集合M中的元素从小到大排列后所得序列的第n项,其中n<10001。

相关知识

为了完成本关任务,你需要掌握:1.枚举算法的两种框架,2.递推算法的实施步骤,3.问题求解思路。

枚举算法的两种框架

枚举的本质就是从所有的备选答案中去查询正确的解。一般的,使用枚举算法需要满足两个基本条件:

  • 备选答案的数量是确定的或是有限个数的;
  • 备选答案的范围在求解之前也应该是确定的。

枚举算法有两种常见的框架:区间枚举和递增枚举。它们在不同的任务中都有着各自的优势。

区间枚举的主要思想是对于一个给定的闭区间,从该区间的下限一直逐个枚举到该区间的上限,其伪代码如下所示:

  1. n=0;
  2. for(k=<区间下限>;k<=<区间上限>;k++)
  3. {
  4. <运算操作序列>;
  5. if(<约束条件>)
  6. {
  7. printf(<满足要求的解>);
  8. n++;
  9. }
  10. }
  11. printf(<解的个数>);

递增枚举的主要思想是从给定的枚举起点开始,一直逐个枚举,直到找到满足条件的解,程序结束,其伪代码如下所示:

  1. k=<枚举起点>
  2. while(1)
  3. {
  4. k++;
  5. <运算操作序列>;
  6. if(<约束条件>)
  7. {
  8. printf(<满足要求的解>);
  9. return;
  10. }
  11. }
递推算法的实施步骤

递推的定义:给定一个数的序列H0​,H1​,...,Hn​,...,若存在整数n0​,使当n>n0​时,可以用等号(或大于号、或小于号)将Hn​与其前面的某些项Hi​,i∈[0,n0​]联系起来,这样的式子就叫做Hn​的递推式。递推算法的具体实施步骤如下:

    确定递推变量:递推变量可以是简单变量,也可以是一维或多维数组;
    建立递推关系:递推关系是递推的依据,是解决递推问题的关键;
    确定初始值和边界条件:根据问题最简单情形的数据,确定递推变量的初始值和边界条件,这是递推的基础;
    对递推过程进行控制:和枚举算法互相配合,完成递推问题的求解。

问题求解思路

该问题已经给出了递推变量x和递推关系2x+1,5x−1,以及初始值为x=1,但是不知道边界条件,也就是说要递推出足够多的项,然后才能找到排序后的第n项。

借助从小到大排序这一限制条件,我们可以设置两个变量,分别控制递推关系2x+1和5x−1的递推进程,使得依次递推出的序列是有序的,那么边界条件即为第n项递推的结束。

例如n=10时,通过递推可以得到第10项为31,具体步骤如下:

1.第1步:给定数组m,从下标1开始存储有序递推数列,初始值m[1]=1,设定p2​=p5​=1,分别表示递推关系F2​(x)=2x+1和F5​(x)=5x−1的上一项递推变量x在数组m中的索引。

2.第2步:分别计算两个递推式的值,若F2​(m[p2​])<F5​(m[p5​]),则数组m的第i=2项为m[2]=F2​(m[p2​]),并更新p2​=p2​+1;若F2​(m[p2​])>F5​(m[p5​]),则数组m的第i=2项为m[2]=F5​(m[p5​]),并更新p5​=p5​+1;若F2​(m[p2​])=F5​(m[p5​]),则数组m的第i=2项为m[2]=F2​(m[p2​]),并更新p2​=p2​+1,p5​=p5​+1。

3.第3步至第n步:按照第2中的递推过程,依次递推出第3项,第4项,直到第n项的值。

上面是一些书面化的解释,我这里用自己的语言总结一下,结合图示服用!

        首先要搞清楚一个点:

                这个题给了我们一个M包含一个m[1]=1的值,还有两个式子。

                目的就是求经过两个式子计算的结果,比较他们的大小,然后小的放入数组m当中(那么小的指针就要自增移动)

                大的先不动(也就是说指针在此处不动)

------------举例:

                如图所示,蓝色区域是一个整体,是执行完里面的语句之后,数组m中p5和p2所指向的位置。

                p2、p5原本都指向1的位置,经计算比较,p2小于p5,那么就把p2指向的值赋值给数组m也就是3,然后p2自增一

                p2-->指向位置2

                p5-->指向位置1

                如此比较,小的赋值,自增,大的不动。

                相同则都自增,随便一个赋值数组

编程要求

本关的编程任务是补全右侧代码片段mainBeginEnd中间的代码,具体要求如下:

  • main中,根据枚举和递推的基本思想,计算出双关系递推数列的前n项,并从小到大存储到数组m中,下标从1开始,即第一项为m[1]=1

测试说明

平台将自动编译补全后的代码,并生成若干组测试数据,接着根据程序的输出判断程序是否正确。

以下是平台的测试样例:

测试输入:10 预期输出:31

#include <iostream>
#include <cstdio>
 
int main(int argc, const char * argv[]) {
 
    long long m[10001];     // 数组:从小到大保存的集合M的元素
    int n;                  // 查询第n项
    int p2;                 // F2(x)=2x+1的索引指针
    int p5;                  // F5(x)=5x-1的索引指针
    
    scanf("%d",&n);
    
    m[1]=1;
    p2=1;
    p5=1;
    
    // 请在这里补充代码,完成本关任务
    /********* Begin *********/
    
    int sum = m[1];
	for (int i=2;i<=n;i++){
       int temp2 = 2*m[p2]+1;
       int temp5 = 5*m[p5]-1;

       if(temp2 < temp5){
            m[i] = temp2;
            p2++;}
        else if(temp2 > temp5){
            m[i] = temp5;
            p5++;
        }
        else{
            m[i] = temp2;
            p2++;
            p5++;
        }
    }
 
    /********* End *********/
 
    
    printf("%d\n",m[n]);
 
    return 0;
}
 

代码很简单就不一一赘述了,流程就是

        循环遍历数组位置、比较式子结果大小,小的赋值数组此时位置,并小的指针自增1,大的不动,继续下一个循环

        若相等就是都自增,然后p2赋值就行了。

        

  • 19
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值