Computer >> 컴퓨터 >  >> 프로그램 작성 >> Python

Python의 Ajob Sequence에서 시퀀스를 선택할 수 있는 방법의 수를 찾는 프로그램

<시간/>

Ajob 언어라는 이상한 언어가 있다고 가정합니다. 글자 수는 무한합니다. 우리는 이 언어로 n개의 단어를 알고 있습니다. 첫 번째 단어는 1자 길이이고, 두 번째 단어는 2자 길이입니다. 그리고 단어의 모든 글자는 고유합니다. n 단어 중 하나를 선택하고 그로부터 하위 시퀀스를 형성하는 경우. 하위 시퀀스의 길이는 원래 단어의 길이보다 k 작아야 합니다. 예를 들어 선택한 단어의 길이가 L이라고 하면 하위 시퀀스의 길이는 (L - k)여야 합니다. 길이가 k보다 작은 단어가 있으면 해당 단어를 선택해서는 안 됩니다. 그리고 두 부분 시퀀스의 길이가 다르거나 같은 위치에 다른 문자가 포함되어 있으면 두 부분 시퀀스가 ​​서로 다릅니다. 우리는 결과 모듈로 p와 p i 소수를 찾아야 합니다.

따라서 입력이 n =6, k =5, p =11과 같으면 출력은 7이 됩니다.

이 문제를 해결하기 위해 다음 단계를 따릅니다. −

  • 빈 사전 메모 하나 만들기
  • n :=n + 1, k :=k + 1
  • fact :=하나의 요소가 있는 목록 1
  • 1~p-1 범위의 i에 대해 다음을 수행합니다.
    • 팩트의 끝에 (팩트의 마지막 요소 * i mod p) 삽입
  • p가 메모에 있으면
    • inv_fact :=메모[p]
  • 그렇지 않으면
    • inv :=0과 1의 두 요소가 있는 목록
    • 2~p-1 범위의 i에 대해 다음을 수행합니다.
      • inv 끝에 (p - p/i의 바닥 * inv[p mod i] mod p) 삽입
    • inv_fact :=하나의 요소가 있는 목록 1
    • 1~p-1 범위의 i에 대해 다음을 수행합니다.
      • inv_fact 끝에 삽입(inv_fact * inv[i] mod p의 마지막 요소)
    • 메모[p] :=inv_fact
  • ret :=1
  • n> 0일 때 수행
    • n1 :=n 모드 p
    • k1 :=k 모드 p
    • k1> n1이면
      • 0을 반환
    • ret :=ret * 사실[n1] * inv_fact[k1] * inv_fact[n1 - k1] 모드 p
    • n :=(n/p)의 바닥
    • k :=k/p의 바닥
  • 반환

예시

이해를 돕기 위해 다음 구현을 살펴보겠습니다. −

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))

입력

6, 5, 11

출력

7