Python中查找相邻k次交换且不多于k次交换后序列数量的程序
假设我们有一个数组A,其中包含前n个自然数。现在,我们需要找到经过恰好k次相邻交换后可以得到多少个序列(S1)?同时,我们需要找到经过最多k次交换后可以得到多少个序列(S2)?这里的相邻交换是指交换索引i和i + 1处的元素。
那么,如果输入为n = 3,k = 2,则输出将是3,6,因为 –
原始数组是[1, 2, 3]
- 经过2次相邻交换后:我们可以得到[1, 2, 3]、[2, 3, 1]、[3, 1, 2]。因此,S1 = 3
- 经过最多2次交换后:
- 经过0次交换:[1, 2, 3]
- 经过1次交换:[2, 1, 3]、[3, 2, 1]、[1, 3, 2]。
- 经过2次交换:[1, 2, 3]、[2, 3, 1]、[3, 1, 2]
因此,S2 = 6
要解决这个问题,我们需要按照以下步骤进行 –
- p = 10 ^ 9 + 7
- A:仅包含1个元素的数组
- C:仅包含1个元素的数组
- 对于n在2到n + 1的范围内,进行以下操作
- B = A,A = 仅包含1个元素1的数组
- D = C,C = 仅包含1个元素1的数组
- 对于x在1到k + 1和1到n所有数字的总和的最小值之间的范围内,进行以下操作
- (A的最后一个元素 + (当x小于B的大小时,B [x]否则0) – (当0 <= x-n时,B [x-n]否则0)) mod p,在A的末尾插入
- 对于x在1到n-2之间的范围内,进行以下操作
- 在C的末尾插入(D [x] +(n-1)* D [x-1])模p
- 在C的末尾插入(n * D的最后一个元素)mod p
- 返回A [从k mod 2到k的索引的所有元素之和]取模p和C [n-1和k的最小值]的总和
示例
看下面的实现,以获得更好的理解 –
p = 10**9+7
def solve(n, k):
A = [1]
C = [1]
for n in range(2,n+1):
B = A
A = [1]
D = C
C = [1]
for x in range(1,min(k+1,n*(n-1)//2+1)):
A.append((A[-1] + (B[x] if x<len(B) else 0) - (B[x-n] if 0<=x-n else 0)) % p )
for x in range(1,n-1):
C.append((D[x]+(n-1)*D[x-1]) % p)
C.append(n*D[-1] % p)
return sum(A[k%2:k+1:2]) % p,C[min(n-1,k)]
n = 3
k = 2
print(solve(n, k))
输入
3,2
输出
3,6