結果
| 問題 | No.3670 Fast Knapsack |
| コンテスト | |
| ユーザー |
harurun
|
| 提出日時 | 2026-09-01 23:03:23 |
| 言語 | PyPy3 (7.3.23) |
| 結果 |
AC
|
| 実行時間 | 1,199 ms / 2,500 ms |
| + 639µs | |
| コード長 | 2,053 bytes |
| 記録 | |
| コンパイル時間 | 443 ms |
| コンパイル使用メモリ | 96,084 KB |
| 実行使用メモリ | 132,796 KB |
| 最終ジャッジ日時 | 2026-09-04 23:05:09 |
| 合計ジャッジ時間 | 15,230 ms |
|
ジャッジサーバーID (参考情報) |
judge4_0 / judge2_0 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 25 |
ソースコード
import sys
import pypyjit
pypyjit.set_param(
"threshold=1,"
"function_threshold=1,"
"trace_eagerness=1,"
"decay=0"
)
W = 63
# r bit 左シフトするときに、
# 63bit の範囲に残る下位部分を取り出すための mask
LOW_MASK = [0] * W
r = 1
while r < W:
LOW_MASK[r] = (1 << (W - r)) - 1
r += 1
def solve() -> None:
data = list(map(int, sys.stdin.buffer.read().split()))
pos = 0
T = data[pos]
pos += 1
out = [""] * T
tc = 0
while tc < T:
N = data[pos]
S = data[pos + 1]
pos += 2
# +1 は最上位 word からの carry 用
top_word = S // W
bits = [0] * (top_word + 2)
# 部分和 0
bits[0] = 1
end = pos + N
while pos < end:
a = data[pos]
pos += 1
if a > S:
continue
q = a // W
r = a - q * W
# x + a <= S となり得る最大 source word
src = (S - a) // W
if r == 0:
while src >= 0:
bits[src + q] |= bits[src]
src -= 1
else:
low_mask = LOW_MASK[r]
rr = W - r
while src >= 0:
x = bits[src]
dst = src + q
# dst word の bit r..62
bits[dst] |= (x & low_mask) << r
# 次の word の bit 0..r-1
bits[dst + 1] |= x >> rr
src -= 1
# S 以下で最も大きい立っている bit を探す
wi = top_word
rb = S - wi * W
x = bits[wi] & ((1 << (rb + 1)) - 1)
if x:
ans = wi * W + x.bit_length() - 1
else:
wi -= 1
while bits[wi] == 0:
wi -= 1
ans = wi * W + bits[wi].bit_length() - 1
out[tc] = str(ans)
tc += 1
sys.stdout.write("\n".join(out))
if __name__ == "__main__":
solve()
harurun