题目描述
牛牛的作业薄上有一个长度为 n 的排列 A,这个排列包含了从1到n的n个数,但是因为一些原因,其中有一些位置(不超过 10 个)看不清了,但是牛牛记得这个数列顺序对的数量是 k,顺序对是指满足 i < j 且 A[i] < A[j] 的对数,请帮助牛牛计算出,符合这个要求的合法排列的数目。
输入描述:
每个输入包含一个测试用例。每个测试用例的第一行包含两个整数 n 和 k(1 <= n <= 100, 0 <= k <= 1000000000),接下来的 1 行,包含 n 个数字表示排列 A,其中等于0的项表示看不清的位置(不超过 10 个)。
输出描述:
输出一行表示合法的排列数目。
示例1
输入
5 5
4 0 0 2 0
输出
2
解析:
# 数列还原
# 原理:参考实例[4,0,0,2,0]
# 1)第一步,计算已知数子的对数sum1,即[4,2],0种;复杂度n^2
# 第二步,前提,首先列举出所有的未知数字的排列组合,保存起来;
# 以上的例子为:[(1, 3, 5), (1, 5, 3), (3, 1, 5), (3, 5, 1), (5, 1, 3), (5, 3, 1)]
# 选取其中一个组合为例(1, 3, 5),分别将三个数中的一个插入原数组中[4,0,0,2,0]
# 例如,第一次插入的是1,原数组变为[4,1,0,2,0]通过分别计算将1,与1左边的和右边的数字进行比较(即[4]和[2])
# 2)计算出(1, 3, 5)相应的对数,然后进行累加的sum2
# 判断sum1+sum2 == k?
# itertools用于字符串/数字的全排列,itertools.permutations("abc",3),输出结果为abc, acb, bac, bca, cab和cba。
# copy用于复制数组,python采用的是:如果参数可变就为引用传递,否则则是值传递。(列表list可变[],元组tuple不可变())
import itertools
import copy
n, k = map(int, input().split())
array = list(map(int, input().split()))
# 计算第一个值sum1
firstNum = 0;
for i in range(len(array)):
if array[i] != 0:
for j in range(i, len(array)):
if array[j] != 0 and array[i] < array[j]:
firstNum += 1
# unknownNum存储未知的数字
unknownNum = []
tempArray = [0 for i in range(0, n + 1)]
for i in array:
if i != 0:
tempArray[i] = 1
for i in range(1,n + 1):
if tempArray[i] == 0:
unknownNum.append(i)
# 计算每一个未知排列,所对应的数量sum2
def calvalue(list, arr):
sum = 0
j = 0
for i in range(len(arr)):
if arr[i] == 0:
arr[i] = list[j]
j += 1
# 分别计算左右
for k in range(i):
if arr[k] != 0 and arr[k] < arr[i]:
sum += 1
for k in range(i + 1, len(arr)):
if arr[k] != 0 and arr[k] > arr[i]:
sum += 1
return sum
# 存储所有的未知数的排列情况
unknownArray = list(itertools.permutations(unknownNum, len(unknownNum)))
result = 0
for x in range(len(unknownArray)):
total = 0;
temp = unknownArray[x]
temp = list(temp)
# 由于传的是直接引用,数组array的值会改变,所以需要深度(完全复制,不共享内存)复制
temparr = copy.deepcopy(array)
total = calvalue(temp, temparr) + firstNum
if total == k:
result += 1
print(result)
# 全排列函数permutation,需要使用递归来列举,也是一个知识点(参考网络)
# 除了使用模块,当然可以自己写一个函数来实现:
# def permutation(xs): #简化问题,假定形参xs是列表
# if len(xs) == 0 or len(xs) == 1:
# return [xs]
# result = []
# for i in xs:
# temp_list = xs[:] #对xs进行切片操作,使得temp_list的值和xs一样 但是temp_list的改变不影响xs
# temp_list.remove(i)
# temp = permutation(temp_list) #使用递归 生成删掉一个元素的xs的全排列
# for j in temp: #对temp中的每一项再进行遍历
# j[0:0] = [i] #在index 0 的位置插入之前删去的i
# result.append(j)
# return result
#
# 这个函数就可以对列表内的元素进行全排列。
# permutation([0,1,2])得到[[0,1,2],[0,2,1],[1,0,2],[1,2,0],[2,0,1],[2,1,0]]