1.到 X 星球旅行的游客都被发给一个整数,作为游客编号。
X 星的国王有个怪癖,他只喜欢数字 3,53,5 和 77。
国王规定,游客的编号如果只含有因子:3,5,73,5,7,就可以获得一份奖品。
我们来看前 1010 个幸运数字是:
35791521252735453579152125273545
因而第 1111 个幸运数字是: 4949
小明领到了一个幸运数字 5908470958750559084709587505,他去领奖的时候,人家要求他准确地说出这是第几个幸运数字,否则领不到奖品。
请你帮小明计算一下,5908470958750559084709587505 是第几个幸运数字。
思路:
cnt = 0
for i in range(50):
for k in range(50):
for j in range(50):
a = 3**i
b = 5**k
c = 7**j
if a*b*c<=59084709587505:
cnt+=1
print(cnt-1) #这里的减1是因为当i,j,k=0的时候这三个数相乘=1,1不是幸运数字
2
python模板:
order = [0] * 20
chosen = [0] * 20
n = 0
def calc(x):
if x == n + 1:
ansTem = ''
for i in range(1, n + 1):
print(order[i], end=' ')
print('')
return
for i in range(1, n+1):
if chosen[i] == 1:
continue
order[x] = i
chosen[i] = 1
calc(x+1)
chosen[i] = 0
order[x] = 0
if __name__ == '__main__':
n = int(input())
# print(name)
calc(1)
这里用到了DFS的模板
针对DFS我们再看一道题
现在小学的数学题目也不是那么好玩的。 看看这个寒假作业:
□ + □ = □
□ - □ = □
□ × □ = □
□ ÷ □ = □
每个方块代表 1~13 中的某一个数字,但不能重复。
比如:
6 + 7 = 13
9 - 8 = 1
3 * 4 = 12
10 / 2 = 5
以及:
7 + 6 = 13
9 - 8 = 1
3 * 4 = 12
10 / 2 = 5
就算两种解法。(加法,乘法交换律后算不同的方案)
你一共找到了多少种方案?
import os
import sys
b, vis = [0]*15, [0]*15
ans = 0
def dfs(num):
global ans
if num == 13:
if b[10] == b[11]*b[12]: #把除法改写成乘法,因为除法运行比较麻烦
ans += 1 #更新答案
return
#剪枝过程,如果前几个式子无法满足,那后面九个数组合而成的式子也无法满足
if num == 4 and b[1] + b[2] != b[3]:
return
if num == 7 and b[4] - b[5] != b[6]:
return
if num == 10 and b[7] * b[8] != b[9]:
return
for i in range(1, 14):
if vis[i] == 0: #表示该层数还未使用
b[num] = i
vis[i] = 1 #表示该层数已经计算过了,需要进入下一层
dfs(num+1) #进入下一层
vis[i] = 0 #回溯,重新回到if语句那一行
dfs(1) #一般这里填1
print(ans)
输出结果:
3. 排列函数permutations 这个函数在itertools模块里。
功能:连续返回由 iterable序列中的元素生成的长度为r的排列。
如果r未指定或为None,r默认设置为 iterable 的长度,即生成包含所有元素的全排列。
代码示例:
from itertools import permutations
s = ['a', 'b', 'c']
for i in permutations(s, 2):
a = i[0] + i[1]
print(a)
结果:
不过这个方法慎用,经常会有超时的情况。
来看道题目吧
如果用 a b c d 这 4 个字母组成一个串,有 4!=24 种,如果把它们排个序,每个串都对应一个序号:
abcd 0
abdc 1
acbd 2
acdb 3
adbc 4
adcb 5
bacd 6
badc 7
bcad 8
bcda 9
bdac 10
bdca 11
cabd 12
cadb 13
cbad 14
cbda 15
cdab 16
cdba 17
⋯⋯
现在有不多于 10 个两两不同的小写字母,给出它们组成的串,你能求出该串在所有排列中的序号吗?
输入描述
输入一行,一个串。
输出描述
输出一行,一个整数,表示该串在其字母所有排列生成的串中的序号。注意:最小的序号是 0。
输入输出样例
示例
输入
bdca
输出
11
题解:
先将输入的东西搞成一个列表,再用sort进行排序,最后用permutations()进行全排列
from itertools import*
olds = input()
news = list(olds)
news.sort()
cnt = 0
for ele in permutations(news):
a = ''.join(ele)
if olds == a:
print(cnt)
break
cnt += 1
4.尺取法
尺取法是一种线性的高效率算法。记 (L, R ) 为一个序列内以L为起点的最短合法区间,如果R随L的增大而增大的,就可以使用尺取法。具体的做法是不断的枚举 L,同时求出R。因为 R 随 L增大而增大,所以总时间复杂度为 O(n)
核心就是L 和 R
对于一些需要考虑运行时间的题,尺取法是个不错的选择
反向扫描:i、j方向相反,i从头到尾,j从尾到头,在中间相会。 “左右指针”
同向扫描:i、j方向相同,都从头到尾,速度不同,例如让j跑在i前面。“快慢指针”
来看几道题目
1.题目描述
给定一个长度为 n 的字符串 S。请你判断字符串 S 是否回文。
输入描述
输入仅 11行包含一个字符串 S。
1≤∣S∣≤10^6,保证 S 只包含大小写、字母。
输出描述
若字符串 S 为回文串,则输出 Y,否则输出 N。
输入输出样例
示例 1
输入
abcba
输出
Y
示例 2
输入
abcbb
输出
N
思路:反向扫描的两个指针i、j,指针i从左向右扫描,指针j从右向左扫描,在中间i < j处相遇并停止
伪代码:
输入s
i=0
j=len(s)-1
if i==j: print('Y')
else:
while s[i]==s[j]:
i+=1
j-=1 #让i和j相互靠近
if j<=i:
print('Y')
break
else:
print("N")
2.【问题描述】输入n个整数,放在数组a[]中。找出其中的两个数,它们之和等于整数m。
思路:
(1)对数组从小到大排序;
(2)i和j分别指向头和尾,i和j向中间移动:
a[i] + a[j] > m,让j减1:大的变小
a[i] + a[j] < m,让i加1:小的变大
直至a[i] + a[j] = m
3.给定一个长度为 n 的序列 a1,a2,⋯,an 和一个常数 S。
对于一个连续区间如果它的区间和大于或等于 S,则称它为美丽的区间。
对于一个美丽的区间,如果其区间长度越短,它就越美丽。
请你从序列中找出最美丽的区间。
输入描述
第一行包含两个整数n,S,其含义如题所述。
接下来一行包含 n 个整数,分别表示a1,a2,⋯,an。
10≤N≤10^5,1×ai≤10^4,1≤S≤10^8。
输出描述
输出共一行,包含一个整数,表示最美丽的区间的长度。
若不存在任何美丽的区间,则输出 0。
输入输出样例
示例 1
输入
5 6
1 2 3 4 5
输出
2
最美丽区间:1. 左端点与右端点的差值越小,这个区间就越美丽
2.左端点与右端点的和大于或等于s
题解:
n, s = map(int, input().split())
a = list(map(int, input().split())) #输入多个数字的时候用这种形式输入
i, j = 0, 0
sum = 0
ans = 1e8 #初始化一个较大的数
while i < len(a): #遍历整个列表
if sum < s: #如果区间小于s,则一直相加
sum += a[i] #区间加和
i += 1
else:
ans = min(i - j, ans) #寻找最美丽区间
sum -= a[j]
j += 1
if ans == 0: #i和j不重合
print('0')
else:
print(ans)