|
@@ -0,0 +1,95 @@
|
|
|
|
|
+package leetcode.p2787;
|
|
|
|
|
+
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
|
+import java.util.Arrays;
|
|
|
|
|
+import java.util.List;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * @ProjectName: LeetCode
|
|
|
|
|
+ * @FileName: Solution
|
|
|
|
|
+ * @Author: 杨逸
|
|
|
|
|
+ * @Data:2025/8/12 11:48
|
|
|
|
|
+ * @Description: https://leetcode.cn/problems/ways-to-express-an-integer-as-sum-of-powers/description/
|
|
|
|
|
+ * 2787. 将一个数字表示成幂的和的方案数
|
|
|
|
|
+ */
|
|
|
|
|
+class Solution {
|
|
|
|
|
+ int mod = (int)1e9 + 7;
|
|
|
|
|
+ long f[][];
|
|
|
|
|
+ List<Integer> list = new ArrayList<>();
|
|
|
|
|
+ public int numberOfWays(int n, int x) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 1.先算出所以可能的取值
|
|
|
|
|
+ * 2.然后就是选与不选的思路
|
|
|
|
|
+ * 问题转化为:以目标值为背包容量,以幂的值为物品的重量,求恰好装满背包的组合数
|
|
|
|
|
+ * 3.最后改成记忆化搜索
|
|
|
|
|
+ */
|
|
|
|
|
+ double current = 1;
|
|
|
|
|
+ while (true){
|
|
|
|
|
+ double pow = myPow(current, x);
|
|
|
|
|
+ if (pow > n){
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ list.add((int)pow);
|
|
|
|
|
+ current++;
|
|
|
|
|
+ }
|
|
|
|
|
+ f = new long[list.size()][n+1];
|
|
|
|
|
+ for (int i = 0; i < f.length; i++) {
|
|
|
|
|
+ Arrays.fill(f[i],-1);
|
|
|
|
|
+ }
|
|
|
|
|
+ return (int)(dfs(list.size()-1,n) % mod);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private long dfs(int i, int n) {
|
|
|
|
|
+ //边界
|
|
|
|
|
+ if(i < 0){
|
|
|
|
|
+ return n == 0 ? 1 : 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ //剪枝
|
|
|
|
|
+ if(n == 0){
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(n < 0){
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ //取缓存
|
|
|
|
|
+ if(f[i][n] != -1){
|
|
|
|
|
+ return f[i][n];
|
|
|
|
|
+ }
|
|
|
|
|
+ //不选
|
|
|
|
|
+ long res = dfs(i-1,n);
|
|
|
|
|
+ //能选
|
|
|
|
|
+ if(n>= list.get(i)){
|
|
|
|
|
+ res += dfs(i-1,n-list.get(i));
|
|
|
|
|
+ }
|
|
|
|
|
+ //缓存
|
|
|
|
|
+ return f[i][n] = res;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @param x 底数
|
|
|
|
|
+ * @param n 指数
|
|
|
|
|
+ * @return double
|
|
|
|
|
+ * @description: 快速幂
|
|
|
|
|
+ * @author: 杨逸
|
|
|
|
|
+ * @data:2025/08/12 19:11:26
|
|
|
|
|
+ * @since 1.0.0
|
|
|
|
|
+ */
|
|
|
|
|
+ private double myPow(double x, int n) {
|
|
|
|
|
+ long N = n;
|
|
|
|
|
+ if (N < 0){
|
|
|
|
|
+ //负指数的情况
|
|
|
|
|
+ N = -N;
|
|
|
|
|
+ x = 1 / x;
|
|
|
|
|
+ }
|
|
|
|
|
+ double res = 1;
|
|
|
|
|
+ double cur = x;
|
|
|
|
|
+ while(N != 0){
|
|
|
|
|
+ if ((N & 1) == 1){
|
|
|
|
|
+ res *= cur;
|
|
|
|
|
+ }
|
|
|
|
|
+ cur *= cur;
|
|
|
|
|
+ N >>= 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ return res;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|