Program to find number of ways we can select sequence from Ajob Sequence in Python


Suppose there is a strange language called Ajob language. It has infinite number of letters. We know n words in this language. The first word is one character long, second one is two character long and so on. And all letters in a word are unique. If we select any one of the n words and form a subsequence from it. The length of the subsequence should be k less than the length of original word. For an example, if the length of the chosen word is say L, then the length of the subsequence should be (L - k). If any word with length smaller than k, then, you must not choose that word. And two subsequences are different to each other when the lengths of them are different or they contain different characters in the same position. We have to find result modulo p, and p i a prime.

So, if the input is like n = 6, k = 5, p = 11, then the output will be 7.

To solve this, we will follow these steps −

  • create one empty dictionary memo
  • n := n + 1, k := k + 1
  • fact := a list with one element 1
  • for i in range 1 to p - 1, do
    • insert (last element of fact * i mod p) at the end of fact
  • if p is present in memo, then
    • inv_fact := memo[p]
  • otherwise,
    • inv := a list with two elements 0 and 1
    • for i in range 2 to p - 1, do
      • insert (p - floor of p/i * inv[p mod i] mod p) at the end of inv
    • inv_fact := a list with one element 1
    • for i in range 1 to p - 1, do
      • insert (last element of inv_fact * inv[i] mod p) at the end of inv_fact
    • memo[p] := inv_fact
  • ret := 1
  • while n > 0, do
    • n1 := n mod p
    • k1 := k mod p
    • if k1 > n1, then
      • return 0
    • ret := ret * fact[n1] * inv_fact[k1] * inv_fact[n1 - k1] mod p
    • n := floor of (n/p)
    • k := floor of k/p
  • return ret

Example

Let us see the following implementation to get better understanding −

memo = {}
def solve(n, k, p):
   n += 1
   k += 1
   fact = [1]
   for i in range(1, p):
      fact.append(fact[-1] * i % p)
   if p in memo:
      inv_fact = memo[p]
   else:
      inv = [0, 1]
      for i in range(2, p):
         inv.append(p - p // i * inv[p % i] % p)
      inv_fact = [1]
      for i in range(1, p):
         inv_fact.append(inv_fact[-1] * inv[i] % p)
      memo[p] = inv_fact
   ret = 1
   while n > 0:
      n1 = n % p
      k1 = k % p
      if k1 > n1:
         return 0
      ret = ret * fact[n1] * inv_fact[k1] * inv_fact[n1 - k1] % p
      n //= p
      k //= p
   return ret

n = 6
k = 5
p = 11
print(solve(n, k, p))

Input

6, 5, 11

Output

7

Updated on: 23-Oct-2021

117 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements