0
点赞
收藏
分享

微信扫一扫

带分数,连号区间数

吃面多放酱 2022-03-11 阅读 23

文章目录

带分数

题目描述
100 可以表示为带分数的形式:100 = 3 + 69258 / 714

还可以表示为:100 = 82 + 3546 / 197

注意特征:带分数中,数字 1~9 分别出现且只出现一次(不包含 0 )。

类似这样的带分数,100 有 11 种表示法。

输入描述
从标准输入读入一个正整数 N(N<1000)。

输出描述
程序输出该数字用数码 1~9 不重复不遗漏地组成带分数表示的全部种数。

注意:不要求输出每个表示,只统计有多少表示法!

输入输出样例
示例
输入

100

输出

11

运行限制
最大运行时间:3s
最大运行内存: 64M

分析

  • dfs加全排序问题,容易超时所以要考虑到剪枝!!!

在这里插入图片描述
注意,切割后的全排列会包含a,b,c所有取值结果(这点在剪枝操作中会有神奇的操作)

  • 公式抽象:n = a + b / c
  • 由于n是定值,并且b / c > 0 ,所以n > a,所以len(n) >= len(a),在这里我们就确定了a的最大切割范围。
  • 由a的切割范围我们得到了a,那么b/c就是一个定值。如果我能确认c,b就自动能出来了。但这里注意,切割范围可能依然很大,必须通过一切操作再切割一次。记得:切割后的全排列的会包含a,b,c所有的取值结果,所以我们这里以最后一位数作为c的末位,c的末位知道我们就可以用公式:c*(n-a)%10直接求b的尾数,如果尾数等于0和尾数等于c的末位,那么直接可以continue。
  • 知道b的尾数有什么用呢?可以知道b的切割范围,查找到b的尾数的位置,如果b的尾数在a的切割范围和b的尾数在c的切割范围(其实这个可以不用,因为前面有判断是否等于末位,所以b必然不会在c的切割范围内)
  • 最后就是判断n = a + b / c是否成立了。
  • 以上操作需要拼接所以全排列的时候用字符串比较合适,排列出来的元组可以直接拼接。

运行代码

from itertools import permutations
n = input()
a_len_max = len(n) 
n = int(n)
res = 0
for x in permutations("123456789"): # 所有全排列
    for al in range(a_len_max): # 划定a的范围
        a = int("".join(x[:al+1])) # a
        if a >= n:
            continue
        
        c_last = int(x[-1]) # c末位
        b_last = c_last*(n-a)%10 # b末位
        if b_last == 0 or b_last == c_last:
            continue
        
        b_loc = x.index(str(b_last))
        if b_loc <= al : # 在a的切割范围
            continue

        b = int("".join(x[al+1:b_loc+1]))
        c = int("".join(x[b_loc+1:]))
        if b / c + a == n:
            res+=1
print(res)  

通过截图

在这里插入图片描述

连号区间数

题目描述
小明这些天一直在思考这样一个奇怪而有趣的问题:

在 1 ~ N 的某个全排列中有多少个连号区间呢?

这里所说的连号区间的定义是:

如果区间 [L,R] 里的所有元素(即此排列的第 L 个到第 R 个元素)递增排序后能得到一个长度为 R-L+1 的"连续"数列,则称这个区间连号区间。

当 N 很小的时候,小明可以很快地算出答案,但是当 N 变大的时候,问题就不是那么简单了,现在小明需要你的帮助。

输入描述
第一行是一个正整数 N(1≤N≤50×10^4), 表示全排列的规模。

第二行是 N 个不同的数字 Pi(1≤Pi≤N),表示这 N 个数字的某一全排列。

输出描述
输出一个整数,表示不同连号区间的数目。

输入输出样例
示例
输入

4
3 2 4 1

输出

7

运行限制
最大运行时间:5s
最大运行内存: 64M

分析

在这里插入图片描述

  • 题目是真不好理解,直接可以用上面的图去理解。(不太懂为什么一个数也算递增排序)
  • 这题很容易想到暴力,我们其实只要找到最大值和最小值,然后如果最大值减最小值等于区间位置之差,那么就一定是满足条件的。这里需要注意,全排列数字是不重复的

运行代码

n = int(input())
nums = list(map(int,input().split()))
res = 0
for i in range(n):
    Max = nums[i]
    Min = nums[i]
    for j in range(i,n):
        if nums[j] > Max:
            Max = nums[j]
        if nums[j] < Min:
            Min = nums[j]
        if j-i == Max-Min:
            res+=1


print(res)

通过截图

在这里插入图片描述

如有错误,敬请指正,欢迎交流,谢谢♪(・ω・)ノ

举报

相关推荐

0 条评论