Python|总和为S、位数为OR的最小元素数为X

184 阅读3分钟

给出两个整数XS,任务是找出最小长度的正整数序列,使它们的元素之和为S,它们的元素的位数OR(^)X. 如果不存在满足上述条件的序列,打印-1.

例子

**输入。**X = 13, S = 23
**输出。**3
**解释。**其中一个长度为3的有效序列是[9, 9, 5]
,这样9+9+5=23,9^9^5=13。
另一个有效的序列是{13, 9, 1}
可以证明,没有长度小于3的有效数组。

**输入。**X = 6, S = 13
输出。-1

**办法。**这个问题可以根据以下观察来解决。

观察到的情况。

  • X是序列中的一个元素。 考虑到X的二进制表示,我们想找到一个长度为N的整数序列A,这样。
    • 如果X的第i位是0,Ai的第i位在所有1≤i≤N的情况下是0。
    • 如果X的第1位是1,则Ai的第1位是1,至少有一个1≤i≤N。
    • 我们知道,元素之和S≥X。为了满足第二个条件,我们可以简单地将X作为序列的一个元素。
  • **在序列的长度上进行二进制搜索。**假设一个长度N满足给定条件。
    • 我们可以简单地在之前的长度为N的序列中加入一个0,因此,长度为(N+1)也会满足所有的条件。
    • 我们不能肯定地说,我们是否能根据给定的长度为N的结果生成一个满足所有条件的长度为(N-1)的序列,因此,我们将不得不再次检查。
    • 我们可以对序列的长度应用二进制搜索。如果当前的长度m满足所有条件,我们就寻找一个较小的长度值,否则,我们就寻找一个较大的长度值。
    • 如果在下限和上限之间不存在可能的m,答案是-1。
  • 二进制搜索的检查功能。我们需要确定一个长度为m的序列是否可以有等于S的元素之和以及等于X的元素之位或。
    • 如果我们被给定一个长度m,每个(设定)位可以有m个副本。由于其中一个元素是X,我们对每个设定的位都有m-1个副本。
    • 我们的问题简化为找到一个长度为(m-1)的序列,其总和为(S-X),位数为或等于(Y?X=X)
    • 我们从最高位到最低位(不包括最低位)遍历X的位。考虑第i位。
      • X的第1位是0。 在(S-X)中,第i位应该没有设置位的副本。
      • X的第1位是1:(S-X)中的第1位最多可以有(m-1)个设置位的副本。所有多余的副本可以转移到(S-X)的第(i+1)位(通过乘以2的系数)。
  • 对于最低位。
    • **X的最低位是0:**如果(S-X)中最低位有任何设置位的副本,长度为m的序列不存在,否则它存在。
    • **X的最低位是1:**如果(S-X)中最低位的设置位的拷贝数超过(m-1),长度为m的序列不存在,否则它存在。

下面是上述方法的实现。

Python

# Python3 program for the above approach
def possible(x, s, m):

	# domain validation for function
	if (s < 0 or x < 0 or m < 0):
		return False
	i = 30
	while(i >= 0):
		if (((x >> i) & 1) == 1):
			temp = s // (1 << i)
			temp = temp if (temp < m) else m
			s -= temp * (1 << i)
		if s <= 0:
			break
		i -= 1
	return True if (s == 0) else False

# Function to find minimum length
# of sequence
def minLength(x, s):
	foul = s + 1
	left = 0
	right = s + 1
	m = 0
	s = s - x
	while (left < right):
		m = (left + (right - left) // 2)
		val = possible(x, s, m - 1)
		if (val == True):
			right = m

		else:
			left = m + 1

	ret = left if (left < foul) else -1
	return ret

# Driver code
if __name__ == "__main__":
	X = 13
	S = 23

	# Function call
	print(minLength(X, S))

# This code is contributed by Rohit Pradhan.

输出

3

**时间复杂度。**O(logS * logX) = O(log (S+X))
**辅助空间。**O(1)