<p>A <strong>good meal</strong> is a meal that contains <strong>exactly two different food items</strong> with a sum of deliciousness equal to a power of two.</p>

<p>You can pick <strong>any</strong> two different foods to make a good meal.</p>

<p>Given an array of integers <code>deliciousness</code> where <code>deliciousness[i]</code> is the deliciousness of the <code>i<sup>​​​​​​th</sup>​​​​</code>​​​​ item of food, return <em>the number of different <strong>good meals</strong> you can make from this list modulo</em> <code>10<sup>9</sup> + 7</code>.</p>

<p>Note that items with different indices are considered different even if they have the same deliciousness value.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> deliciousness = [1,3,5,7,9]
<strong>Output:</strong> 4
<strong>Explanation: </strong>The good meals are (1,3), (1,7), (3,5) and, (7,9).
Their respective sums are 4, 8, 8, and 16, all of which are powers of 2.
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> deliciousness = [1,1,1,3,3,3,7]
<strong>Output:</strong> 15
<strong>Explanation: </strong>The good meals are (1,1) with 3 ways, (1,3) with 9 ways, and (1,7) with 3 ways.</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= deliciousness.length &lt;= 10<sup>5</sup></code></li>
	<li><code>0 &lt;= deliciousness[i] &lt;= 2<sup>20</sup></code></li>
</ul>

# prefix sum
# TC: O(n * log(m + m)) => O(nlog(m))
# SC: O(n)
class Solution:
    def countPairs(self, deliciousness: List[int]) -> int:
        hashmap = {}
        
        # 记录[0,i]这个范围内的最大值和第二大的值
        # 在这个范围内的两个数的和 不可能超过 最大值和第二大的值 之和
        result = 0
        max_val = deliciousness[0]
        second_max_val = deliciousness[0]
        for val in deliciousness:
            if val > second_max_val and val > max_val:
                second_max_val = max_val
                max_val = val
            elif val > second_max_val:
                second_max_val = val
            n = 0
            # 当前最大值和第二大的值的和 就是当前[0,i]这个区间能够寻找到2**n的范围
            # 不能让(2**n)无限的增长
            # 当区间两个值不可能构成(2**n)时，停止搜索
            while 2 ** n <= max_val + second_max_val:
                target = (2 ** n) - val
                n += 1
                if target < 0:
                    continue
                result += hashmap.get(target, 0)
                

            hashmap[val] = hashmap.get(val, 0) + 1
        
        return result % (10 ** 9 + 7)


1426