1. 巨大的错误 (错排公式)
想象一个原来有序的书架,每本书都有原本的位置,现在要改变他们的位置,让每本书的位置都不是原来的位置。
现在假设我们有n本书,要打乱他们的顺序:
- 第n本书需要放到前n-1个位置,有n-1种选择,假设放到了位置k
- 位置k的书需要找一个位置放
- 如果放到了n,就相当于n,k互换位置,剩下的n-2本书是相同的子问题
- 如果没有放到n,那么可以想象k的位置原本就在n,k不能放在n,剩下的n-1本书是相同的子问题
因此递推公式就是 D ( n ) = ( n − 1 ) ∗ ( D ( n − 1 ) + D ( n − 2 ) ) D(n)=(n-1)*(D(n-1)+D(n-2)) D(n)=(n−1)∗(D(n−1)+D(n−2))
if __name__ == '__main__':
n = int(input())
a= [0] * 21
a[1], a[2] = 0, 1
for i in range(3,n+1):
a[i] = (i-1)*(a[i-1]+a[i-2])
print(a[n])
2. 歌词中找单词(二分)
首先遍历歌词,找到每一个歌词出现的位置,存到列表里,然后每次寻找字母位置的时候使用二分法,保证子序列的递增。
from collections import defaultdict
if __name__ == '__main__':
n = int(input())
words = []
for i in range(n):
words.append(input())
lyris = input()
word_num = defaultdict(list)
for index,word in enumerate(lyris):
word_num[word].append(index)
# 遍历每一个单词
for word in words:
flag = True
# 上一个单词位置
now = -1
# 遍历每一个字母
for j in word:
l,r = 0, len(word_num[j])-1
while l < r:
mid = l + r >> 1
if word_num[j][mid] > now:
r = mid
else:
l = mid + 1
if not word_num[j]:
flag = False
break
# 到了最后一位,且不满足
if l == len(word_num[j])-1 and word_num[j][l] < now:
flag = False
break
now = word_num[j][l]
if flag:
print('YES')
else:
print('NO')
3. 字符串斐波那契
递归,第n个字符串由n-1和n-2字符串得到,判断来自于哪个,继续递归。
def find(n,c):
if n == 0:
print(a0[c-1])
return
if n == 1:
print(a1[c-1])
return
if c <= length[n-2]:
find(n-2, c)
else:
find(n-1, c-length[n-2])
if __name__ == '__main__':
a0 = 'IAKIOI'
a1 = 'WHENWILLSCORLLOFTAIWUCOMEOUT!!!'
length = [0]*81
length[0] = len(a0)
length[1] = len(a1)
n,c = map(int, input().split())
for i in range(2, n+1):
length[i] = length[i-1] + length[i-2]
find(n,c)