結果
問題 |
No.1978 Permutation Repetition
|
ユーザー |
![]() |
提出日時 | 2025-06-12 14:06:26 |
言語 | PyPy3 (7.3.15) |
結果 |
WA
|
実行時間 | - |
コード長 | 2,866 bytes |
コンパイル時間 | 238 ms |
コンパイル使用メモリ | 82,696 KB |
実行使用メモリ | 77,056 KB |
最終ジャッジ日時 | 2025-06-12 14:06:32 |
合計ジャッジ時間 | 4,097 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 15 WA * 29 |
ソースコード
import sys from math import gcd from collections import defaultdict MOD = 10**9 + 7 def main(): sys.setrecursionlimit(1 << 25) N, M = map(int, sys.stdin.readline().split()) A = list(map(int, sys.stdin.readline().split())) A = [a-1 for a in A] # Step 1: Decompose A into cycles and count their lengths visited = [False] * N cycle_counts = defaultdict(int) for i in range(N): if not visited[i]: cycle_len = 0 j = i while not visited[j]: visited[j] = True j = A[j] cycle_len += 1 cycle_counts[cycle_len] += 1 # Step 2: Factorize M and get all divisors def get_divisors(m): divisors = set() for i in range(1, int(m**0.5)+1): if m % i == 0: divisors.add(i) divisors.add(m//i) return sorted(divisors) divisors = get_divisors(M) # Precompute factorial and inverse factorial up to N max_n = max(cycle_counts.keys()) if cycle_counts else 0 max_fact = max(max_n, N) fact = [1] * (max_fact + 1) for i in range(1, max_fact + 1): fact[i] = fact[i-1] * i % MOD inv_fact = [1] * (max_fact + 1) inv_fact[max_fact] = pow(fact[max_fact], MOD-2, MOD) for i in range(max_fact-1, -1, -1): inv_fact[i] = inv_fact[i+1] * (i+1) % MOD # Precompute d_pows for each d and g total = 1 for d, k in cycle_counts.items(): valid_gs = [] for g in divisors: if (M // g) == 0: continue if gcd(d, M // g) != 1: continue valid_gs.append(g) # Now compute the generating function's coefficient for x^k dp = [0] * (k + 1) dp[0] = 1 for g in valid_gs: # Precompute d^g mod MOD d_pow_g = pow(d, g, MOD) # Precompute 1/g mod MOD inv_g = pow(g, MOD-2, MOD) # Contribution for each group of size g: (d^g / g) = d^g * inv_g mod MOD contrib = d_pow_g * inv_g % MOD # Iterate from high to low to avoid overwriting for i in range(k, g-1, -1): max_m = i // g current_contrib = 1 for m in range(1, max_m + 1): term = contrib * current_contrib % MOD term = term * inv_fact[m] % MOD prev = i - m * g if prev < 0: break dp[i] = (dp[i] + dp[prev] * term) % MOD current_contrib = current_contrib * contrib % MOD # The coefficient is dp[k], multiply by k! to get the contribution contribution = dp[k] * fact[k] % MOD total = total * contribution % MOD print(total % MOD) if __name__ == "__main__": main()