สมมติว่าเราได้รับตัวเลข n และถูกขอให้เขียนการเรียงสับเปลี่ยนที่เป็นไปได้ทั้งหมดด้วยจำนวนเต็มบวกสูงถึง n จากนั้นการเรียงสับเปลี่ยนจะถูกจัดเรียงตามพจนานุกรมและเรียงลำดับจาก 1 ถึง n ในบรรดาการเรียงสับเปลี่ยนทั้งหมด มีการเรียงสับเปลี่ยนหนึ่งครั้งและเรียกว่าการเรียงสับเปลี่ยนแบบพิเศษ ตอนนี้ท่ามกลางการเปลี่ยนแปลงพิเศษ ค่าสามารถลืมได้ ค่าที่ถูกลืมจะถูกแทนที่ด้วย 0s เราต้องหาการเรียงสับเปลี่ยนที่สามารถเท่ากับการเรียงสับเปลี่ยนดั้งเดิม จากนั้นเราเพิ่มหมายเลขเปอร์สเปคทีฟเพื่อให้ได้ผลรวม ค่าผลรวมจะถูกส่งกลับเป็นผลลัพธ์ของโปรแกรม
ดังนั้น หากอินพุตเป็นเหมือนการเรียงสับเปลี่ยนพิเศษ (input_arr) =[0, 2, 0], n =3 ผลลัพธ์จะเป็น 7 อาจมีการเรียงสับเปลี่ยนที่เป็นไปได้สองแบบ หนึ่งคือ [1, 2, 3] และอีกอันคือ [3, 2, 1] ตัวเลขของการเรียงสับเปลี่ยนเหล่านี้คือ 2 และ 5 ตามลำดับ ดังนั้นผลลัพธ์จะเป็น 5 + 2 =7
เพื่อแก้ปัญหานี้ เราจะทำตามขั้นตอนเหล่านี้ -
- mod :=10^9 + 7
- i2 :=2 ^ (โมดูโล - 2) โมดูโล
- ข้อเท็จจริง :=รายการใหม่ที่มีค่า 1
- สำหรับ x ในช่วง 1 ถึง n+1 ให้ทำ
- แทรก (รายการสุดท้ายของข้อเท็จจริง * x) mod modulo ที่ส่วนท้ายของข้อเท็จจริง
- cnt :=จำนวนครั้งที่เกิด 0 ใน input_arr
- ถ้า cnt เท่ากับศูนย์ แล้ว
- res :=0
- seen_list :=รายการใหม่
- สำหรับแต่ละดัชนี i เริ่มต้นจาก 1 และรายการ x ใน input_arr ทำ
- tmp_val :=ดัชนีที่สามารถแทรก x ลงใน seenList เพื่อรักษาลำดับการจัดเรียง
- res :=res + fact[n-i] *(x - 1 - tmp_val)
- res :=res mod modulo
- แทรก x ลงใน seen_list ที่ตำแหน่ง tmp_val
- ผลตอบแทน + 1
- มิฉะนั้น
- ik :=(cnt ^ (modulo-2)) โมดูโล
- miss :=รายการขนาด n ใหม่ที่เริ่มต้นด้วยค่า True
- สำหรับแต่ละ x ใน input_arr ทำ
- ถ้า x ไม่เหมือนกับ 0 แล้ว
- คิดถึง[x - 1] :=ผิด
- ถ้า x ไม่เหมือนกับ 0 แล้ว
- miss_srtd :=รายการใหม่
- tmp :=0
- สำหรับแต่ละดัชนี i เริ่มต้นจาก 1 และรายการ x ใน miss ทำ
- ถ้า x ไม่ใช่ศูนย์ แล้ว
- ใส่ i ต่อท้าย miss_srtd
- tmp :=tmp + ฉัน
- ถ้า x ไม่ใช่ศูนย์ แล้ว
- pre :=รายการใหม่ที่เริ่มต้นด้วย 0
- สำหรับ x ใน miss ทำ
- แทรกก่อน[-1] + x ต่อท้ายประโยค
- cnt_cu :=0
- s :=tmp mod modulo * ik mod modulo
- srtdw :=รายการใหม่
- res :=0
- z :=0
- สำหรับแต่ละดัชนี i เริ่มต้นจาก 1 และรายการ x ใน input_arr ทำ
- ถ้า x ไม่ใช่ศูนย์ แล้ว
- l :=ตำแหน่งที่สามารถแทรก x ลงใน srtdw เพื่อรักษาลำดับการจัดเรียง
- tmp_val :=ตำแหน่งที่สามารถแทรก x ลงใน srtdw เพื่อรักษาลำดับการจัดเรียง
- l :=l + z * (ตำแหน่งที่สามารถแทรก x ลงใน miss_srtd เพื่อรักษาลำดับการเรียงลำดับ) mod modulo * ik mod modulo
- p :=x - 1 - l
- p :=p * ข้อเท็จจริง[cnt]
- p :=p โมดูโล
- แทรก x ลงใน srtdw ที่ตำแหน่ง tmp_val
- cnt_cu :=cnt_cu + cnt - ก่อน[x]
- มิฉะนั้น
- l :=cnt_cu
- l :=l * ik
- l :=l + z * โมดูล modulo i2
- p :=s - 1 - l
- p :=p * ข้อเท็จจริง[cnt]
- p :=p โมดูโล
- z :=z + 1
- res :=res + p * fact[n-i] โมดูโล
- res :=res mod modulo
- ถ้า x ไม่ใช่ศูนย์ แล้ว
- return(res + fact[cnt]) modulo
ตัวอย่าง
ให้เราดูการใช้งานต่อไปนี้เพื่อความเข้าใจที่ดีขึ้น -
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))
อินพุต
[0, 2, 0], 3
ผลลัพธ์
7