結果
問題 | No.125 悪の花弁 |
ユーザー |
![]() |
提出日時 | 2025-01-17 02:32:53 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 149 ms / 5,000 ms |
コード長 | 2,248 bytes |
コンパイル時間 | 2,896 ms |
コンパイル使用メモリ | 82,304 KB |
実行使用メモリ | 113,432 KB |
最終ジャッジ日時 | 2025-01-17 02:32:58 |
合計ジャッジ時間 | 4,561 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 6 |
ソースコード
#yukicoder125 悪の花弁#愚直解をがんばって書くdef brute(K, C):from itertools import permutationsB = []for i, Ci in enumerate(C):B.extend( [i] * Ci )n = len(B)ans = set()for P in permutations(B):for i in range(n):Q = tuple( P[i:] + P[:i] )if Q in ans:breakelse:ans.add(P)return len( ans )def solve(K, C):#花弁の枚数をN, gcd(C)をgとする#gの約数個を単位に並べる これをシフトしよう#下処理として約数列挙まではやっておくN = sum(C)MOD = 10 ** 9 + 7 #998244353にしていました すいませんfact = [ v := 1 ] + [ v := v * i % MOD for i in range(1, N + 1) ]finv = [ v := pow(v, -1, MOD) ] + [ v := v * i % MOD for i in range(N, 0, -1) ]finv.reverse()gcd = lambda x, y: gcd(y, x % y) if y else abs(x)g = 0for Ci in C:g = gcd(g, Ci)D = []for i in range(1, g + 1):if i ** 2 > g:breakif g % i == 0:D.append(i)if i ** 2 != g:D.append(g // i)D.sort() #周期列挙#一旦円環のことは忘れる#F[i]: 同色g // i枚を1セットとして一列に並べる場合の数# ただし、F[i]の候補が複数ある場合は最大のg // i → 最小のi でカウントする#G[i]: 同色g // i枚を1セットとして一列に並べる場合の数F = [0] * (g + 1)G = [0] * (g + 1)for i in D:pair = g // iG[i] = fact[ N // pair ]for Ci in C:G[i] *= finv[ Ci // pair ]G[i] %= MOD#約数包除でF[i]を求める 包除というか力業だけどfor i in D:F[i] = G[i]for j in D:if j < i and i % j == 0:F[i] -= F[j]F[i] %= MOD#答えを計算 g // i枚1セットなので総セット数は N // ( g // i) セットans = 0for i in D:cnt = N // ( g // i )ans += F[i] * pow(cnt, -1, MOD)ans %= MODreturn ans#実行print( solve( K := int(input()), C := list(map(int, input().split())) ) )