python练习题(三)——Consecutive Integer

系列文章目录

python练习题(一)——A+B Problem

python练习题(二)——Words


这个题对我来说是有点难的,看了一下平台上的通过率,通过率只有31%

一、Consecutive  Integer

题目描述:

2005年百度之星初赛有这么一道题,一个正整数有可能被表示为m(m>1)个连续正整数之和,如:

15=1+2+3+4+5

15=4+5+6

15=7+8

但现在你的任务是判断给定的整数n能否表示成连续的m(m>1)个整数之和

解答要求:

时间限制:1000ms,内存限制:100mb

输入:

输入只有一个整数n(1<n<2^30+1)

输出:

若n能表示成连续的m个正整数之和则输出'YES',否则输出‘NO’

输入样例:

15

输出样例:

YES

二、代码详情

先上代码,再说解题思路

def func():
    n=int(input())
    flag=False
    for i in range(1,n):
        res=i
        for j in range(i+1,n):
            res+=j
            if res==n:
                flag=True
                print('YES')
                break
        if flag:
            break
    if not flag:
        print('NO')

if __name__ =='__main__':
    func()


'''
输入:15
输出:YES
'''

三、解题思路

首先先说结论,上面的代码时可以运行出结果,而且结果也是符合预期的,但是提交代码的时候并没有通过,因为上述代码的运行时间3997.3ms,超过了题目的要求。接下来说一下思路:

题目中要求是连续的几个正整数,所以,我第一个想法就是两层循环:

第一层循环从1开始

第二层循环从2开始,然后记录1+2的值,接下来继续执行第二层循环,此时第二层循环到3,然后记录1+2+3的值……一次类推,如果第一层循环从1开始到遍历结束没有符合的结果,跳出内层循环

此时,第一层循环从2开始

第二层循环从3开始,记录2+3的值……然后执行内层循环计算2+3+4+……

……

但是还有一个问题,我需要做到满足条件的时候随时终止循环,于是我添加了一个flag标签,初始的时候赋值为False,只要满足条件就赋值为True,用来终止循环并通过最后的flag值判断是否打印NO。

四、另辟蹊径

虽然上面的程序也算解决了问题,但是提交代码的时候提示超市,未通过,所以只能换一个想法来解决,我曾设想减少循环的次数,但是盘算了一下,就算减少了可能时间还是超出限制,所以决定换一个思路来解决这个问题。

1、问题分析

首先,如果这个数字N是奇数的话,肯定是满足条件的,奇数总是可以表示成两个连续整数的和

接下来需要考虑偶数的情况:

反证:假设这个偶数可以被换成连续的自然数相加的形式,那么可以表示为:

\bg_white \fn_jvn x+\left ( x+1 \right )+\left ( x+2 \right )+\left ( x+3 \right )+\cdots +\left ( x+k \right )=n

用等差数列求和公式,求出

\left ( 2x+k \right )\left ( k+1 \right )/2=n

 若k+1为偶数,则2x+k为奇数,若k+1为奇数,则2x+k为偶数,所以等号的左边必定是一个奇数一个偶数。将公式转换为\left ( 2x+k \right )\left ( k+1 \right )=2n

因为2n是偶数,左边(2x+k)(k+1)一定有一个数值是偶数。

我们将等式的两边不断地提取公因子2,如果等号的右边可以化成2^m,也就是2的幂,而等式的左边因为存在一个奇数而不能化成2^m,所以式子不可能相等,所以2的幂是不能转换成连续自然数相加的形式

2、伪代码

经过上面的推理,最终问题就简单了。伪代码如下:

输入正整数n;

if   n是奇数:

        print('YES')

elif: n是2的幂: 

        print('YES')

else:

        print('NO') 

3、另一个难题

那么这里就迎来了另一个问题,怎么判断一个数字是不是2的幂?

这里有一个非常巧妙的方法,就是位与运算,首先我们看一下2的幂转在二进制下具有什么特征?

print(bin(2))
print(bin(4))
print(bin(8))
print(bin(16))


'''
0b10
0b100
0b1000
0b10000
'''

都是1后面很多个0,如果将2的幂减去1,转化为二进制是很多个1(比2的幂少一位),如下

print(bin(1))
print(bin(3))
print(bin(7))
print(bin(15))

'''
0b1
0b11
0b111
0b1111

'''

两者与位与运算后得到的结果毫无疑问都是False(位与运算可以在数学啥鞥理解为且的运算,用符号&表示,0&1=0,0&0=0,1&1=1)

于是判断一个数字是否为2的幂,就可以简单写为:

if n&(n-1)==0:
    print('n是2的幂')
else:
    print('n不是2的幂')

五、最终版代码

def func():
    n=int(input())
    if n%2==1:
        print('YES')
    elif n&(n-1)==0:
        print('YES')
    else:
        print('NO')
if __name__=='__main__':
    func()

代码用时:12.7ms   

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值