結果
問題 |
No.3001 ヘビ文字列
|
ユーザー |
![]() |
提出日時 | 2025-01-14 23:11:28 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 1,176 ms / 1,500 ms |
コード長 | 3,476 bytes |
コンパイル時間 | 666 ms |
コンパイル使用メモリ | 82,548 KB |
実行使用メモリ | 218,372 KB |
最終ジャッジ日時 | 2025-01-14 23:12:26 |
合計ジャッジ時間 | 57,247 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 4 |
other | AC * 83 |
ソースコード
#yukicoder3001 ヘビ文字列 #愚直解 明らかにN - 1文字の変更でヘビ文字列になる点に注意 from itertools import product, combinations def brute(T): #1. Tを種類圧縮 N = len(T) P = sorted(set(T)) Q = {Ti: i for i, Ti in enumerate(P)} T = [ Q[Ti] for Ti in T ] n = len(Q) #出現する種類数 #2. 気合いで全列挙 計算量はしらない for k in range(N): #replace個数 for B in combinations( range(N), r = k ): #replace位置 for C in product( range(n), repeat = k ): #replace先 S = T[:] for Bi, Ci in zip(B, C): S[Bi] = Ci for t in range(1, N): #S[t: t + N]とS[0: N]が一致するか判定 if all( S[i] == S[ (t + i) % N ] for i in range(N) ): return k, S #素因数分解 def factorial(N): F = [] for n in range(2, N + 1): if n > N: break if ( N % n == 0 ) and ( c := 0 ) == 0: while N % n == 0 and ( c := c + 1 ): N //= n F.append((n, c)) if N > 1: F.append((N, 1)) return F #約数列挙 def divisor(N): F = factorial(N) D = [1] for p, e in F: nD = [] for n in D: nD.append( n * ( q := 1 ) ) for _ in range(e): nD.append( n * ( q := q * p ) ) D = nD D.sort() return D #実験すると N = len(S) = 1441440 のとき、約数が最大で288個 #現在の解法は: #for n in (Nの約数であって、Nでないもの): # c = N # for m in range(n): # c -= ( S[m], S[m + n], S[m + 2n], ・・・ の文字種のうち最大のもの ) #cが最小となるnが理想のswap量。あとはよしなに #for n: (Nの約数全体) とすると Dn = 288 よりループ回数がきつい #でも普通にnは大きい方がよくない?Nの素因数の1種類だけをノックダウンすればよいのでは def solve(T): #丁寧にやらないとTLEするらしい こまった #1. 座標圧縮・Sへの変換 A = [-1] * 26 N = len(T) for i in range(N): A[ ord( T[i] ) - ord('A') ] += 1 c = 0 C = [] for i in range(26): if A[i] != -1: A[i] = c c += 1 C.append( chr( ord('A') + i ) ) D = {Ti: i for i, Ti in enumerate(C)} S = [ A[ ord( T[i] ) - ord('A') ] for i in range(N) ] n = len(D) #2. swap量の候補を全探索し、replace数が最小となるswap量tを検索 rep = N = len(T) rept = -1 A = [0] * n #種類数カウンター F = factorial(N) for Pi, Ei in F: c = N t = N // Pi #tだけswapする for m in range(t): for i in range(m, N, t): A[ S[i] ] += 1 c -= max(A) for i in range(n): A[i] = 0 if rep > c: rep, rept = c, t #3. reptだけswapすると決め打って最終構築 for m in range( rept ): for i in range(m, N, rept): A[ S[i] ] += 1 s = A.index( max(A) ) for i in range(m, N, rept): S[i] = s for i in range(n): A[i] = 0 #4. Sを復元 for i in range(N): S[i] = C[ S[i] ] return ''.join(S) #入力高速化 import sys input = sys.stdin.readline #実行 print( solve(input().strip()) )