Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonで生成したリストから特定の要素のXOR値を求めるプログラム

自然数を含むリストが与えられたとします。まず、このリストから2進表現において「1」が連続して現れる数をすべて取り除き、残った数だけで新しいリストZを作成します。次に、いくつかの整数値を含む別のリストinput_listが与えられるので、Zのうちinput_listで指定されたインデックス位置にある要素のXOR値を求めます。

たとえば、input_list = [3, 4, 5] が入力された場合、出力は 9 になります。

Zのインデックス3、4、5に対応する値はそれぞれ 4、5、8 です。したがって、4 XOR 5 XOR 8 = 9 となります。

解法のアプローチ

この問題を効率的に解く鍵となるのはフィボナッチ数列です。「2進表現に連続する1を含まない数」と「互いに隣接しないフィボナッチ数の和(ゼッケンドルフ表現)」との間には一対一の対応関係があります。この性質を利用すると、リストZを実際に構築しなくても、インデックスkに対応するZの要素を直接計算できます。

具体的には、以下の手順で解きます。

  • 関数 zeck_num() を定義する(引数は k と f_list)
    • res := 0
    • i を f_list のサイズ − 1 から −1 まで、1ずつ減らしながら繰り返す
      • k >= f_list[i] ならば
        • res := res + 2^i
        • k := k − f_list[i]
    • res を返す
  • MOD := 10^9 + 7
  • max_val := 10^18
  • f_list := 値 1 と 2 を含む新しいリストを作成
  • f_list の最後の要素が max_val 以下である間、次を繰り返す
    • f_list の末尾に「最後の要素 + 後ろから2番目の要素」を追加
  • res := 0
  • input_list の各 index について
    • res := res XOR zeck_num(index, f_list)
  • res mod MOD を返す

実装例

理解を深めるために、以下のPythonコードを見てみましょう。

def zeck_num(k, f_list):
    res = 0
    for i in range(len(f_list)-1, -1, -1):
        if k >= f_list[i]:
            res += 2**i
            k -= f_list[i]
    return res

def solve(input_list):
    MOD = 10**9+7
    max_val = 10**18
    f_list = [1, 2]
    while f_list[-1] <= max_val:
        f_list.append(f_list[-1] + f_list[-2])
    res = 0
    for index in input_list:
        res ^= zeck_num(index, f_list)
    return res % MOD

print(solve([3, 4, 5]))

入力

[3, 4, 5]

出力

9

この実装では、あらかじめ10^18までのフィボナッチ数をリスト化しておくことで、任意の大きさのインデックスに対しても高速に対応する値を求められます。各クエリの計算量はフィボナッチ数列の長さに比例する程度であり、非常に効率的です。

  1. Pythonで木の辺を1本取り除いたときの部分木のノード値合計の差の最小値を求めるプログラム

    問題の概要ノードに1からnまでの番号が振られた木があるとします。各ノードには整数値が格納されています。ここで、木からある1本の辺を取り除くと、木は2つの部分木に分割されます。このとき、2つの部分木のノード値の合計の差が最小になるようにしたいと考えます。私たちのタスクは、その最小の差を求めて返すことです。木は辺のリストとして与えられ、各ノードの値も併せて提供されます。例として、n = 6、edge_list = [[1, 2], [1, 3], [2, 4], [3, 5], [3, 6]]、values = [15, 25, 15, 55, 15, 65] が入力された場合、出力は 0 になり

  2. PythonでリストからN個の最大要素を取得する方法

    整数のリストが与えられたとき、その中からN個の大きな要素を取り出して新しいリストとして返すのが、ここでの課題です。本記事では、基本的なループ処理による方法から、Python標準ライブラリを活用した効率的な方法まで、サンプルコードとともに解説します。 例 入力 : [40, 5, 10, 20, 9] N = 2 出力 : [40, 20] アルゴリズム 整数のリストと、取得する要素数Nを受け取ります。 N回のループを実行します。 各ループでリスト内の最大値を探し、新しいリストに格納すると同時に元のリストから削除します。 実装コード def Nnumberele(list1, N):