• home
  • about
  • 全ての投稿
  • ソフトウェア・ハードウェアの設定のまとめ
  • 分析関連のまとめ
  • ヘルスケア関連のまとめ
  • 生涯学習関連のまとめ

半分全列挙

date: 2021-06-19 excerpt: 半分全列挙について

tag: algorithm半分全列挙


半分全列挙について

  • 探索範囲Nを半分に分割する
    • それぞれの探索範囲を探索する
    • 探索結果を合算してbinary search等で個数を求める

例; 典型

問題

  • 競プロ典型 90 問; 051 - Typical Shop

解説

  • pythonの場合はbit全探索するよりitertoolsを使ったほうが早い(上限の個数を限定できるからか)
  • 分割した結果を合算するとき、L * Rを回すとTLEしてしまうので、二分探索をしてO(L log R)にする

解答

import itertools
import collections
import bisect

def main():
    N,K,P=map(int,input().split())
    *A,=map(int,input().split())

    LA, RA = A[:N//2], A[N//2:]

    L=collections.defaultdict(list)
    for k in range(K+1):
        for la in itertools.combinations(LA, k):
            sum_ = 0 if la == [] else sum(la)
            L[k].append(sum_)

    R=collections.defaultdict(list)
    for k in range(K+1):
        for ra in itertools.combinations(RA, k):
            sum_ = 0 if ra == [] else sum(ra)
            R[k].append(sum_)

    for key in list(L.keys()):
        L[key].sort()
    for key in list(R.keys()):
        R[key].sort()

    ans = 0
    for rk, rlst in R.items():
        rem = K-rk
        llst = L[rem]
        for r in rlst:
            ans += bisect.bisect_left(llst, P-r + 1)
    print(ans)

if __name__ == "__main__":
    main()


algorithm半分全列挙 Share Tweet