给出两个整数X和S,任务是找出最小长度的正整数序列,使它们的元素之和为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)