結果
| 問題 |
No.243 出席番号(2)
|
| ユーザー |
|
| 提出日時 | 2025-02-13 01:14:51 |
| 言語 | Python3 (3.13.1 + numpy 2.2.1 + scipy 1.14.1) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 1,861 bytes |
| コンパイル時間 | 606 ms |
| コンパイル使用メモリ | 12,160 KB |
| 実行使用メモリ | 32,076 KB |
| 最終ジャッジ日時 | 2025-02-13 01:15:12 |
| 合計ジャッジ時間 | 19,346 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 6 WA * 24 |
ソースコード
import sys
import numpy as np
MOD = 10**9 + 7
def main():
data = sys.stdin.buffer.read().split()
if not data:
return
# 全入力を整数に変換
data = list(map(int, data))
it = iter(data)
N = next(it)
MAXVAL = 5000
# NumPy 配列で頻度カウント(dtype=np.int64 で十分)
C = np.zeros(MAXVAL, dtype=np.int64)
for _ in range(N):
x = next(it)
# x が MAXVAL 未満であると仮定(問題文の仕様通り)
C[x] += 1
# dp 配列:dp[k] = 「k 個選んだときの通り数」
# dp[0] = 1 で初期化。以降の更新は
# dp[1:] = (dp[1:] + dp[:-1] * C[i]) % MOD
# というベクトル演算で行う
dp = np.zeros(N + 1, dtype=np.int64)
dp[0] = 1
# ここで、for ループは N 回回りますが、内側は NumPy の高速演算となるため十分高速です
for i in range(N):
# ここで dp の更新は「右シフトした dp[:-1] に C[i] を掛けたものを dp[1:] に加算」
dp[1:] = (dp[1:] + dp[:-1] * C[i]) % MOD
# fac[k] = k! mod MOD の配列(長さ N+1)を計算
fac = np.empty(N + 1, dtype=np.int64)
fac[0] = 1
for i in range(1, N + 1):
fac[i] = (fac[i - 1] * i) % MOD
# 最終結果は
# ans = Σ_{i=0}^{N} dp[i] * fac[N - i] * ((-1)**i) (mod MOD)
# (-1)**i は、偶数なら 1、奇数なら MOD-1(= -1 mod MOD)とみなせます
sign = np.empty(N + 1, dtype=np.int64)
sign[::2] = 1 # 偶数番目は 1
sign[1::2] = MOD - 1 # 奇数番目は MOD-1
# fac[N-i] を得るために fac 配列を逆順に
fac_rev = fac[::-1]
# 各項を計算して合計(mod MOD)
ans = int((np.sum(dp * fac_rev % MOD * sign)) % MOD)
sys.stdout.write(str(ans))
if __name__ == '__main__':
main()