Program to find out the sum of numbers where the correct permutation can occur in python


Suppose, we are given a number n and are asked to write all the possible permutations with the positive integers up to n. The permutations are then sorted lexicographically and numbered from 1 to n. Among all the permutations, one permutation is taken and is termed as the special permutation. Now, among the special permutation; the values can be forgotten. The forgotten values are then replaced with 0s. We have to find the permutations that can be equal to the original permutations and then we add their perspective number to obtain a sum. The sum value is returned as the output of the program.

So, if the input is like special permutation (input_arr) = [0, 2, 0], n = 3, then the output will be 7. There can be two possible permutations. One is [1, 2, 3] and the another is [3, 2, 1]. The numbers of these permutations are 2 and 5 respectively. So, the result will be 5 + 2 = 7.

To solve this, we will follow these steps −

  • mod := 10^9 + 7
  • i2 := 2 ^ (modulo - 2) mod modulo
  • fact := a new list containing value 1
  • for x in range 1 to n+1, do
    • insert (last item of fact * x) mod modulo at the end of fact
  • cnt := number of occurrences of 0 in input_arr
  • if cnt is same as zero, then
    • res := 0
    • seen_list := a new list
    • for each index i starting from 1 and item x in input_arr, do
      • tmp_val := the index where x can be inserted into seenList maintaining the sorted order
      • res := res + fact[n-i] *(x - 1 - tmp_val)
      • res := res mod modulo
      • insert x into seen_list at position tmp_val
    • return res + 1
  • otherwise,
    • ik := (cnt ^ (modulo-2)) mod modulo
    • miss := a new list of size n initialized with value True
    • for each x in input_arr, do
      • if x is not same as 0, then
        • miss[x - 1] := False
    • miss_srtd := a new list
    • tmp := 0
    • for each index i starting from 1, and item x in miss, do
      • if x is non-zero, then
        • insert i at the end of miss_srtd
        • tmp := tmp + i
    • pre := a new list initialized with 0
    • for each x in miss, do
      • insert pre[-1] + x at the end of pre
    • cnt_cu := 0
    • s := tmp mod modulo * ik mod modulo
    • srtdw := a new list
    • res := 0
    • z := 0
    • for each index i starting from 1 and item x in input_arr, do
      • if x is non-zero, then
        • l := the position where x can be inserted into srtdw maintaining the sorted order
        • tmp_val := the position where x can be inserted into srtdw maintaining the sorted order
        • l := l + z * (the position where x can be inserted into miss_srtd maintaining the sorted order) mod modulo * ik mod modulo
        • p := x - 1 - l
        • p := p * fact[cnt]
        • p := p mod modulo
        • insert x into srtdw at position tmp_val
        • cnt_cu := cnt_cu + cnt - pre[x]
      • otherwise,
        • l := cnt_cu
        • l := l * ik
        • l := l + z * i2 mod modulo
        • p := s - 1 - l
        • p := p * fact[cnt]
        • p := p mod modulo
        • z := z + 1
        • res := res + p * fact[n-i] mod modulo
        • res := res mod modulo
    • return(res + fact[cnt]) mod modulo

Example

Let us see the following implementation to get better understanding −

import bisect

def solve(input_arr, n):

   modulo = 10 ** 9 + 7
   i2 = pow(2, modulo-2, modulo)
   fact = [1]
   for x in range(1, n+1):
      fact.append(fact[-1] * x % modulo)

   cnt = input_arr.count(0)

   if not cnt:
      res = 0
      seen_list = []
      for i, x in enumerate(input_arr, 1):
         tmp_val = bisect.bisect(seen_list, x)
         res += fact[n-i] * (x - 1 - tmp_val)
         res %= modulo
         seen_list.insert(tmp_val, x)
      return res + 1
   else:
      ik = pow(cnt, modulo-2, modulo)
      miss = [True] * n
      for x in input_arr:
         if x != 0: miss[x-1] = False
      miss_srtd = []
      tmp = 0
      for i, x in enumerate(miss, 1):
         if x:
            miss_srtd.append(i)
            tmp += i
      pre = [0]
      for x in miss:
         pre.append(pre[-1] + x)
      cnt_cu = 0
      s = tmp % modulo * ik % modulo
      srtdw = []
      res = z = 0
      for i, x in enumerate(input_arr, 1):
         if x:
            l = tmp_val = bisect.bisect(srtdw, x)
            l += z * bisect.bisect(miss_srtd, x) % modulo * ik % modulo
            p = x - 1 - l
            p *= fact[cnt]
            p %= modulo
            srtdw.insert(tmp_val, x)
            cnt_cu += cnt - pre[x]
         else:
            l = cnt_cu
            l *= ik
            l += z * i2 % modulo
            p = s - 1 - l
            p *= fact[cnt]
            p %= modulo
            z += 1
         res += p * fact[n-i] % modulo
         res %= modulo
      return (res + fact[cnt])%modulo

print(solve([0, 2, 0], 3))

Input

[0, 2, 0], 3

Output

7

Updated on: 11-Oct-2021

99 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements