สมมุติว่ามีภาษาแปลกๆ เรียกว่า ภาษาอาจ๊อบ มีจำนวนตัวอักษรไม่สิ้นสุด เรารู้ n คำในภาษานี้ คำแรกมีความยาวอักขระหนึ่งตัว คำที่สองยาวสองอักขระ เป็นต้น และตัวอักษรทั้งหมดในคำก็มีเอกลักษณ์เฉพาะตัว หากเราเลือกคำใดคำหนึ่งจาก n คำและสร้างลำดับจากคำนั้น ความยาวของลำดับรองควรน้อยกว่าความยาวของคำต้นฉบับ k ตัวอย่างเช่น หากความยาวของคำที่เลือกคือ L ความยาวของคำที่ตามมาควรเป็น (L - k) หากคำใดมีความยาวน้อยกว่า k คุณต้องไม่เลือกคำนั้น และสองส่วนย่อยจะแตกต่างกันเมื่อความยาวของมันต่างกันหรือมีอักขระต่างกันในตำแหน่งเดียวกัน เราต้องหาผลลัพธ์ modulo p และ p i a ไพรม์
ดังนั้น หากอินพุตเป็น n =6, k =5, p =11 เอาต์พุตจะเป็น 7
เพื่อแก้ปัญหานี้ เราจะทำตามขั้นตอนเหล่านี้ -
- สร้างบันทึกพจนานุกรมเปล่าหนึ่งรายการ
- n :=n + 1, k :=k + 1
- ข้อเท็จจริง :=รายการที่มีองค์ประกอบ 1 อย่าง
- สำหรับ i ในช่วง 1 ถึง p - 1 ทำ
- แทรก (องค์ประกอบสุดท้ายของข้อเท็จจริง * i mod p) ที่ส่วนท้ายของข้อเท็จจริง
- ถ้า p มีอยู่ในบันทึกช่วยจำ
- inv_fact :=บันทึก[p]
- มิฉะนั้น
- inv :=รายการที่มีสององค์ประกอบ 0 และ 1
- สำหรับฉันในช่วง 2 ถึง p - 1 ทำ
- แทรก (p - ชั้นของ p/i * inv[p mod i] mod p) ที่ส่วนท้ายของ inv
- inv_fact :=รายการที่มีองค์ประกอบ 1 อย่าง
- สำหรับ i ในช่วง 1 ถึง p - 1 ทำ
- แทรก (องค์ประกอบสุดท้ายของ inv_fact * inv[i] mod p) ที่ส่วนท้ายของ inv_fact
- บันทึก[p] :=inv_fact
- ret :=1
- ในขณะที่ n> 0, ทำ
- n1 :=n mod p
- k1 :=k mod p
- ถ้า k1> n1 แล้ว
- คืน 0
- ret :=ret * fact[n1] * inv_fact[k1] * inv_fact[n1 - k1] mod 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