python蓝桥杯备赛经典例题(程序员面试算法宝典)

蓝桥杯备赛注意事项

先易后难,逐个击破

先易后难,的确是一种有效的工作方法,符合事物循序渐进的发展规律。从容易的事情做起,有利于积累经验,摸清事物内在规律,在攻克难事时起到事半功倍的作用。但从另一个角度看,先易后难也容易前半程热情高涨,而后半程动力逐步减少,阻力日益增大,形成久拖不决的局面。许多事情半途而废,许多改革无法深入,许多工程成为烂尾工程,贻误难题解决的最佳时机,原因大多在此。史载,北宋在北伐北汉时遇到挫折,制定了所谓“先南后北先易后难”的方针。可是等到统一南方之后再回过头北伐,北汉身后已站着一个强大的契丹。错失了北伐的最好时机,导致北宋在军事上处于被动状态。

很多时候,先难后易则事易,先易后难则事难。抓落实,促改革,也要有一种越是困难越向前的精神。难有时恰恰是主要矛盾所在,见难而上,全力攻克,也是抓住主要问题、紧扣主要矛盾、牵住问题的牛鼻子。主要问题和主要矛盾解决了,其他问题和矛盾也会迎刃而解。

关于比赛时的小技巧

比赛的时候,因为考生来考场时间早晚不一,离正式考试会有一段时间,这段时间监考官会讲一些考试的注意事项,当了解完这些如果还没开考的话,你可以提前在你的电脑上写一些你平时积累的通用函数(算法),例如与冒泡排序、栈、二叉树构建、贪心、动态规划、dp、等等一些通用方法…(请尽情发挥想象),然后考试的时候直接调用函数或者方法即可

专题备战1-----基本数字运算

计算机软件技术与数学是不可分割的有机整体,蓝桥杯的填空题上多有类似的真题出现,很多企业在招聘时,往往非常在意求职者的数学能力,编程语言是很简单的东西,只需要熟悉一种语言,其他语言也会很容易实现,而数学素养的高低却不然,需要长时间的学习与积累,直接决定了未来求职者的职业生涯发展。所以,面试官在考察求职者时,也比较喜欢出此类题目。

约数个数

【问题描述】
求一个数的约数个数,n=1200000【只计算正约数】
【答案提交】
这是一道填空题,你只需要计算结果后提交即可。本题的结果是一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分

count=2 #初始化count=2,1及本身就是约数
n=int(input())
for i in range(2,n):  #正约数
    if n % i == 0:
        count += 1
print(count)
#做循环时,切忌只写n,求约数是从1开始的,不是从0开始,会报错

【计算结果】96

不使用循环输出1到100

【问题描述】
实现一个函数,要求在不使用循环的前提下输出1到100
【答案提交】
考虑递归实现

def prints(n):
    if n>0:
        prints(n-1) 
        print(str(n))
if __name__=="__main__":
    prints(100)

如何在不能使用库函数的条件下计算n的平方根

【题目描述】
给定一个数n,求出它的平方根,比如16的平方根为4,要求不能使用库函数。
【分析与解答】
正数n的平方根可以通过计算一系列的近似值来获得,每个近似值都比前一个更加接近准确值,直到找到满足精度要求要求的那个数的位置。具体而言,可以找出第一个近似值是1,接下来的近似值则可以通过下面的公式来获得:a[i+1]=(a[i]+n/a[i])/2
【运行结果】
4的平方根是2.0
3的平方根是1.7320508075688772
【代码实现】

def SquareRoot(n,e):
    new=n
    last=1.0
    while new-last>e:
        new=(new+last)/2 %对半
        last=n/new %逼近
    return new
if __name__=="__main__":
    n=4
    e=0.00000000000000001
    print(str(n)+'的平方根是'+str(SquareRoot(n,e)))
    n1=3
    print(str(n1)+'的平方根是'+str(SquareRoot(n1,e)))

计算一个数的n次方

【问题描述】
给定一个数d和n,如何计算d的n次方?例如:d=2,n=3,d的n次方为8.
【分析与解答】
方法一:蛮力法
可以把n的取值分成如下几种情况:
(1)n=0,那么计算结果肯定为1
(2)n=1,那么计算结果为d
(3)n>0,计算方法:初始化计算结果result=1,然后对result执行n次乘以d的操作,得到的结果就是d的n次方。
(4)n<0,计算方法:为初始化resualt=1,接着对result执行|n|次除以d的操作,得到的结果就是d的n次方;

def power(d,n):
    if n==0:return 1
    if n==1:return d
    result=1.0
    if n>0:
        i=1
        while i<=n:
            result *=d
            i+=1
        return result
    else:
        i=1
        while i<=abs(n):
            result=result/d
            i+=1
        return result
if __name__=="__main__":
    print(power(2,3))
复杂度为O(n)

【运行结果】
8.0
-8.0
0.125
方法二:递归法
(1)n=0,那么计算结果肯定为1
(2)n=1,那么计算结果为d
(3)n>0,计算方法:首先计算2[n/2]的值tmp,如果n为奇数,那么计算结果result=tmptmpd,如果为偶数,那么计算结果result=tmptmp;
(4)n<0,计算方法:首先计算2|[n/2]|的值tmp,如果n为奇数,那么计算结果result=1/(tmp
tmpd),如果为偶数,那么计算结果result=1/(tmptmp);




def power(d,n):
    if n==0:return 1
    if n==1:return d
    tmp=power(d,abs(n)/2)+0.0
    if n>0:
        if n%2==1:%n为奇数
            return tmp*tmp*d
        else:
            return tmp*tmp
    else:
        if n%2==1:
            print(1/(tmp*tmp*d))
            return 1/(tmp*tmp*d)
        else:
            return 1/(tmp*tmp)
if __name__="__main__":
    print(power(3,5))
复杂度为O(log(n))

如何按要求比较两个数的大小

【问题描述】
如何比较a、b两个数的大小?不能使用大于、小于以及if语句。
【分析与解答】
根据绝对值的性质可知,如果|a-b|==a-b,那么max(a,b)=a,否则max(a,b)=b,根据这个思路实现代码
【代码实现】

def maxs(a,b):
    return((a+b)+abs(a-b))/2
if __name__=="__main__":
    print(maxs(5,6))

【运行结果】
6.0

如何求有序数列的第1500个数的值

【题目描述】
一个有序数列,序列中的每一个值都能够被2或3或5所整除,1是这个序列的第一个元素。求第1500个值是多少。
【分析与解答】
方法一:蛮力法
最简单的方法就是用一个计数器来记录满足条件的整数的个数,然后从1开始遍历,如果当前遍历的数能被2或者3或者5整除,那么计数器的值加1,当计数器的值为1500时,当前遍历到的值就是所要求的值。

#计数和判断
def Search(n):
    count=0
    a=1
    while True:
        if a%2==0 or a%3==0 or a%5==0:
            count=count+1 #计数器的值为n时停止计数
        if count==n :
            break
        a=a+1
    return a
if __name__=="__main__":
    print(Search(1500))

方法二:数字规律法
首先可以很容易的得到2,3和5的最小公倍数是30,此外1~30这个区间内满足条件的数有22个{2,3,4,5,6,8,9,10,12,14,15,16,18,20,21,22,24,25,26,27,28,30},由于最小公倍数为30,我们可以猜想,满足条件的数字是否具有周期性(周期为30)呢?通过计算可以发现,31 ~ 60这个区间内满足条件的数也恰好有22个{32,33,34,35,36,38,39,40,42,44,45,46,48,50,51,52,54,55,56,57,58,60},从而发现这些满足条件的数具有周期性(周期为30)。由于1500/22=68,1500%68=4,从而可以得出第1500个数经过了68个周期,然后在第69个周期中抽取第四个满足条件的数{2,3,4,5}.从而得出第1500个数为68*30+5=2045。
【运行结果】
2045

如何判断一个数是不是某个数的平方

【题目描述】
设计一个算法,判断一个数是不是某个数的平方,不能使用开方运算。例如16就满足条件,因为它是4的平方;而15则不满足条件,因为不存在一个数使得平方值为15.
【分析与解答】
方法一:直接计算法:
由于不能使用开方运算,因此最直接的方法就是计算平方。主要思路为:对1到n的每个数i计算他的平方m,如果m<n,那么继续遍历下一个值(i+1),如果m==n,那么说明n是某个数的平方,如果m>n,那么说明n不能表示成某个数的平方。
由于这种方法只需要遍历1到n[0.5]就可以得出结果,因此算法时间复杂度为O(n[0.5])

def isPower(n):
    if n<=0:
        print(str(n)+"不是自然数")
        return False
    i=1
    while i<n:
        result=i*i
        if result==n:
            return True
        elif result>n:
            return False
        i=i+1
if __name__=="__main__":
    n1=15
    n2=16
    if isPower(n1):
        print(str(n1)+"是某个自然数的平方")
    else:
        print(str(n1)+"不是某个自然数的平方")
    if isPower(n2):
        print(str(n2)+"是某个自然数的平方")
    else:
        print(str(n2)+"不是某个自然数的平方")

【运行结果】
15不是某个自然数的平方
16是某个自然数的平方
方法二:二分查找法:
与方法一类似,这种方法的主要思路还是查找1~n的数字中,是否存在一个数m,使得m的平方为n。只不过查找的过程中使用二分查找的方法。具体思路为:首先判断mid=(1+n)/2的平方power与m的大小,如果power>m,那么说明在[1,mid-1]区间继续查找,否则在[mid+1,n]区间继续查找。
由于这种方法使用了二分查找的方法,因此时间复杂度为O(logn),其中,n为数的大小。

def isPower(n):
    low=1
    high=n
    while low<high:
        mid=(low+high)/2
        result=mid*mid
        #接着在1到mid-1
        if result>n:
            high=mid-1
        elif result<n:
            low=mid+1
        else:
            return True
    return False
        

if __name__=="__main__":
    n1=15
    n2=16
    if isPower(n1):
        print(str(n1)+"是某个自然数的平方")
    else:
        print(str(n1)+"不是某个自然数的平方")
    if isPower(n2):
        print(str(n2)+"是某个自然数的平方")
    else:
        print(str(n2)+"不是某个自然数的平方")

如何不使用除法操作符实现两个正整数的除法

【问题描述】
如何不使用除法操作符实现两个正整数的除法?
【分析与解答】
方法一:减法:
被除数不断减去除数,直到相减的结果小于除数,商就是相减的次数,余数为相减后的差。

def divide(m,n):
    count=0 #记录相减的次数
    while m>n:
        m=m-n
        count=count+1
    remain=m #记录余数
    print("商:"+str(count)+"余数:"+str(remain))
if __name__=="__main__":
    m=14
    n=4
    divide(m,n)

【运行结果】
商:3余数:2
方法二:移位法:
方法一所采用的减法操作,还可以用等价加法操作来实现。例如在计算17除以4的时候,可以尝试41,42(4+4),43(4+4+4),直到计算结果大于14的时候就很容易求出商和余数,但是效率较低。下面介绍另外一种增加递增速度的方法:以2的指数进行递增(取2的指数的原因是,2的指数操作可以通过移位操做来实现,有更高的效率),计算41,42,44,48,由于48>17,然后接着对17-4*4=1,进入下一次循环用相同的方法进行计算。

def divide(m,n):
    result=0 #记录相减的次数
    while m>=n:
        multi=1
        while multi*n<=(m>>1):
            multi<<=1
        result+=multi
        m-=multi*n
    print("商:"+str(result)+"余数:"+str(m))
if __name__=="__main__":
    m=14
    n=4
    divide(m,n)

如何只使用+=操作符实现加减乘除运算

【问题描述】
要求只能使用+=操作来实现加减乘除运算?
【分析与解答】
(1)加法操作:实现a+b的基本思路为对a执行b次+=操作即可;
(2)减法操作:实现a-b(a>=b)的基本思路为:不断对b执行+=操作,直到等于a为止,过程中记录+=操作的次数;
(3)乘法操作:实现ab的基本思路为:利用已经实现的加法操作把a相加b次,就得到了ab的值;
(4)除法操作:实现a/b的基本思路为:利用乘法操作,使b不断乘以1,2,…n,直到b*n>b时,就可以得到商为n-1。
【代码实现】

def add(a,b):
    '''
    方法功能:用+=实现加法操作(限制条件:至少有一个非负数)
    输入参数:a,b都是整数,且有一个非负数
    返回值:a+b
    '''
    if a<0 and b<0:
        print("无法计算")
        return -1
    if b>=0:
        i=0
        while i<b:
            a+=1
            i+=1
        return a
    else:
        i=0
        while i<a:
            b+=1
            i+=1
        return b
def minus(a,b):
    '''
    实现功能:用+=实现减法操作(限制条件:被减数大于减数)
    输入参数:a,b都是整数且a>=b
    返回值:a-b
    '''
    if a<b:
        print('无法计算')
        return -1
    result=0
    while b!=a:
        b+=1
        result+=1
    return result
def multi(a,b):
    '''
    实现功能:用+=实现乘法操作(限制条件:两个数都为整数)
    输入参数:a,b都是正数
    返回值:a*b
    '''
    if a<=0 or b<=0:
        print('无法计算')
        return -1
    result=0
    i=0
    while i<b:
        result=add(result,a)
        i+=1
    return result
def divide(a,b):
    '''
    实现功能:用+=实现除法运算(限制条件:两个数都为整数)
    输入参数:a,b都为非负数
    返回值:a/b
    '''
    if a<=0 or b<=0:
        print('无法计算')
        return -1
    result=1
    tmpMulti=0
    while True:
        tmpMulti=multi(b,result)
        if tmpMulti<=a:
           result+=1
        else:
            break
    return result-1
if __name__=="__main__":
    print('和:'+str(add(3,4)))
    print('差:'+str(minus(3,4)))
    print('积:'+str(multi(3,4)))
    print('商:'+str(divide(3,4)))

【运行结果】
和:7
无法计算
差:-1
积:12
商:0

学好数学的秘籍

“数学是工具而非问题,是手段而非目的”
在数学的学习中,首要的问题是明确需求。作为非数学专业出身的“外行”,我们使用数学的目的不是顶天,而是立地;不是上下求索艰深的理论问题,而是将生活中的具体问题抽象化,进而加以解决。

理解数学的工具属性就会自然而然地引出了数学学习中的另一个关键点,那就是工具设计的出发点,也就是所谓的数学思想与数学逻辑。

任何一个工具都不是平白无故地设计出来的,它必然要解决某个特定的问题,比如线性代数与矩阵论是对具体对象的抽象表示与运算,比如概率论和数理统计是对不确定性及其定型定量表示的建模。因此,在掌握每一种数学工具的微观技巧之前,理解它们的宏观目标是更加重要的。只有掌握了工具诞生的背景与目的,才有可能有效地使用它们。

总结起来,我对数学学习的几点拙见是:把握数学的工具属性,学习具体方法时先溯因再求果,勤于思考解决相同问题的不同方法,与解决不同问题的相同方法之间的联系与区别。希望这几条建议能够在数学的学习中助你一臂之力。

总结

(一) 心理准备:蓝桥杯不是ACM,远远不是,没加过实验室就肯定不行的心理对比赛想来未必有好处。单单我认识的,不是实验室的都有四五个拿到国二或者国三的水平,由此可见跟实验室关系并不很大。

(二) 知己知彼:我觉得是这是参加比赛最重要的一点。参加比赛前干什么?当然是真题最好(我觉得四六级也是这样啊)毕竟组委会经过反复斟酌出的题目肯定质量要比那些什么乱七八糟的题目更准确地把握好难度。建议从官网上下最近两次的省赛题,再前两年的可以百度搜,网上也都有。其实当你都做了会发现,蓝桥杯出题就出一个套路。

(1)题目一共有十道,七道小题,三道编程题,每道题分数呈递增(基本是根据难度定的)

(2)比较理智的估计自己的水平。(我觉得干什么都不能眉毛胡子一把抓,这样的结果往往是什么都抓不住)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值