Given a single positive integer x
, we will write an expression of the form x (op1) x (op2) x (op3) x ...
where each operator op1
, op2
, etc. is either addition, subtraction, multiplication, or division (+
, -
, *
, or /)
. For example, with x = 3
, we might write 3 * 3 / 3 + 3 - 3
which is a value of 3.
When writing such an expression, we adhere to the following conventions:
- The division operator (
/
) returns rational numbers. - There are no parentheses placed anywhere.
- We use the usual order of operations: multiplication and division happens before addition and subtraction.
- It's not allowed to use the unary negation operator (
-
). For example, "x - x
" is a valid expression as it only uses subtraction, but "-x + x
" is not because it uses negation.
We would like to write an expression with the least number of operators such that the expression equals the given target
. Return the least number of expressions used.
Example 1:
Input: x = 3, target = 19
Output: 5
Explanation: 3 * 3 + 3 * 3 + 3 / 3. The expression contains 5 operations.
Example 2:
Input: x = 5, target = 501
Output: 8
Explanation: 5 * 5 * 5 * 5 - 5 * 5 * 5 + 5 / 5. The expression contains 8 operations.
Example 3:
Input: x = 100, target = 100000000
Output: 3
Explanation: 100 * 100 * 100 * 100. The expression contains 3 operations.
Note:
2 <= x <= 100
1 <= target <= 2 * 10^8
思路:
1一定是通过x/x得到,然后剩下的部分一定是x的倍数,所以比赛的时候一直想的是划分成若干层,比如x = 3, target = 19:先求6+1,因为3*6+1=19,但是随着层数的嵌套,实际用了多少符号变得不好求了。
Discuss里的答案:独立考虑每个x的次幂使用的个数。具体来说:
求出x的整数次幂数组(一直求到比target大的那个数)A,然后从后往前考虑A,每次考虑用不用当前这个A[i],假设还剩下left需要求出来,那就可以有left/A[i]个A[i],或者(left/A[i])+1个A[i](超过left用减法)
注意:对于每个次幂,前面会加一个符号,比如用3*3*3的时候,在算的时候用的是+3*3*3或者-3*3*3;然而最后算完之后要把前面那个多余的符号去掉,对应 elif y == 0:return -1 这样代码
import functools
import math
class Solution(object):
@functools.lru_cache(None)
def leastOpsExpressTarget(self, x, y):
"""
:type x: int
:type target: int
:rtype: int
"""
k = int(math.log(y, x)) + 1
def dfs(y, k):
if k == 0: return y + y - 1
elif y == 0:return -1
need, left = divmod(y, x**k)
return min(dfs(left, k - 1) + need * k, dfs(x**k - left, k - 1) + (need + 1) * k)
return dfs(y, k)
s=Solution()
print(s.leastOpsExpressTarget(x = 3, y = 19))
import math
class Solution(object):
def leastOpsExpressTarget(self, x, y):
"""
:type x: int
:type target: int
:rtype: int
"""
k = int(math.log(y, x)) + 1
memo = {}
def dfs(y, k):
if (y,k) in memo: return memo[(y,k)]
if k == 0: return y + y - 1
elif y == 0:return -1
need, left = divmod(y, x**k)
res = min(dfs(left, k - 1) + need * k, dfs(x**k - left, k - 1) + (need + 1) * k)
memo[(y,k)] = res
return res
return dfs(y, k)
s=Solution()
print(s.leastOpsExpressTarget(x = 3, y = 19))
有了memo的形式,也可以换成DP