結果
問題 | No.248 ミラー君の宿題 |
ユーザー |
![]() |
提出日時 | 2020-05-13 23:17:43 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 2,103 ms / 5,000 ms |
コード長 | 2,135 bytes |
コンパイル時間 | 937 ms |
コンパイル使用メモリ | 82,432 KB |
実行使用メモリ | 82,520 KB |
最終ジャッジ日時 | 2024-09-14 15:45:17 |
合計ジャッジ時間 | 16,716 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge6 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 18 |
ソースコード
import sysread = sys.stdin.buffer.readreadline = sys.stdin.buffer.readlinereadlines = sys.stdin.buffer.readlinesdef ord_2(n):e = 0while n % 2 == 0:e += 1n >>= 1return edef argmax_distribution(A):U = max(A)n = len(A)dist = [0] * (1<<n)full = (1<<n) - 1dist[full] += 0.5 ** sum(A)for u in range(1, U+1):eq = [0.0] * (1<<n)low = [0.0] * (1<<n)eq[0] = 1.0low[0] = 1.0for i in range(n):t = 0.5 ** (A[i] - u + 1)p_eq = t if A[i] >= u else 0.0p_low = t if u <= A[i] + 1 else 1.0for s in range(1<<i):eq[s^(1<<i)] = eq[s] * p_eqlow[s^(1<<i)] = low[s] * p_lowfor s in range(1, 1<<n):dist[s] += eq[s] * low[full^s]return distdef solve(nums):N = len(nums)dp = [0.0] * (1<<N)A = [ord_2(p-1) for p in nums]def compute_dp(s):if s == 0:return 0.0I = [i for i in range(N) if s & (1<<i)]n = len(I)if n == 1:return 1.0p_loop = 0x = 1.0# gcd で遷移する場合gcd_prob = [1.0] * (1<<n)ind = [0] * (1<<n)for k in range(n):i = I[k]for j in range(1<<k):ind[j + (1<<k)] = ind[j] + (1<<i)gcd_prob[j + (1<<k)] = gcd_prob[j] / (nums[i])gcd_prob[j] -= gcd_prob[j + (1<<k)]p_loop += gcd_prob[-1]B = [A[i] for i in I]for j in range((1<<n) - 1):x += gcd_prob[j] * (dp[ind[j]] + dp[s^ind[j]])# 2^n乗根で遷移する場合p0 = gcd_prob[0]dist = argmax_distribution([A[i] for i in I])p_loop += p0 * dist[-1]for j in range((1<<n) - 1):x += p0 * dist[j] * (dp[ind[j]] + dp[s^ind[j]])return x / (1 - p_loop)for s in range(1<<N):dp[s] = compute_dp(s)return dp[-1]T = int(readline())for _ in range(T):N = int(readline())nums = list(map(int, readline().split()))print(solve(nums))