题目描述
难度分:1041
输入a(0≤a≤60),b(0≤b≤60)和xor(0≤xor<260)。
构造两个在[0,260)中的整数x和y,满足x的二进制中有a个1,y的二进制中有b个1,且x异或y等于xor。
输出x和y。多解输出任意解。如果无法构造,输出−1。
输入样例1
3 4 7
输出样例1
28 27
输入样例2
34 56 998244353
输出样例2
-1
输入样例3
39 47 530423800524412070
输出样例3
540431255696862041 10008854347644927
算法
记忆化搜索
状态定义
dp[i][a][b]表示[0,i−1]位全部构造完,从第i位开始构造,x和y的二进制中分别有a个1和b个1的情况下,后面能否构造出符合xor从第i位到第59位的x和y,满足x⊕y=xor。
状态转移
base case分为以下两种:
- 如果i=60时满足a=b=0,则dp[i][a][b]=
true
。 - 如果a<0或b<0,则dp[i][a][b]=
false
。
一般情况分为以下两种:
- 如果xor在第i位是1,那么x和y在这一位就不同,尝试让x在这一位为1,以及y在这一位为1,状态转移方程为dp[i][a][b]=dp[i+1][a−1][b]∨dp[i+1][a][b−1]。
- 如果xor在第i位是0,那么x和y在这一位就相同,尝试让x和y在这一位为1,以及x和y在这一位为0,状态转移方程为dp[i][a][b]=dp[i+1][a−1][b−1]∨dp[i+1][a][b]。
记忆化搜索完成之后,只要dp[0][a][b]=true
就有解,再从低位到高位进行一次dfs,根据dp状态构造出x和y。否则无解,直接输出−1。
复杂度分析
时间复杂度
状态数量为O((log2U)3),U为xor的值域,单次转移的时间复杂度为O(1)。因此,整个算法的时间复杂度为O((log2U)3)。
空间复杂度
空间消耗的瓶颈就在于记忆化搜索时对DP
状态的缓存,即为状态数量O((log2U)3),这也是整个算法的额外空间复杂度。
python 代码
from functools import lru_cache
a, b, xor = map(int, input().split())
x, y = 0, 0
@lru_cache(None)
def dfs1(i: int, a: int, b: int) -> bool:
if a < 0 or b < 0:
return False
if i == 60:
return a == 0 and b == 0
if xor>>i&1:
# x和y在此位必须不同
return dfs1(i + 1, a - 1, b) or dfs1(i + 1, a, b - 1)
else:
return dfs1(i + 1, a - 1, b - 1) or dfs1(i + 1, a, b)
def dfs2(i: int, a: int, b: int) -> None:
if i == 60:
return
global x, y
if xor>>i&1:
if dfs1(i + 1, a - 1, b):
x |= 1<<i
dfs2(i + 1, a - 1, b)
elif dfs1(i + 1, a, b - 1):
y |= 1<<i
dfs2(i + 1, a, b - 1)
else:
if dfs1(i + 1, a - 1, b - 1):
x |= 1<<i
y |= 1<<i
dfs2(i + 1, a - 1, b - 1)
elif dfs1(i + 1, a, b):
dfs2(i + 1, a, b)
if dfs1(0, a, b):
dfs2(0, a, b)
print(x, y)
else:
print(-1)