Scala 将X表示为唯一自然数的n次幂之和
我最近在休息时间一直在玩HackerRank,在解决这个问题时遇到了一些困难:效率 问题陈述:给定两个整数X和N,找出将Scala 将X表示为唯一自然数的n次幂之和,scala,combinatorics,number-theory,Scala,Combinatorics,Number Theory,我最近在休息时间一直在玩HackerRank,在解决这个问题时遇到了一些困难:效率 问题陈述:给定两个整数X和N,找出将X表示为唯一自然数的N幂和的方法数 示例:X=10,N=2 只有一种方法可以使用低于10的2的幂得到10,那就是1^2+3^2 我的方法 我知道这个问题可能存在一个很好的、优雅的反复出现;但不幸的是我找不到,所以我开始考虑其他方法。我决定从“代码> [1,Z] ,因为 4 ^ 2>10 < /代码>,因此不能是总和为10的(正)数的一部分。在收集了这一系列的数字之后,我把它们都
X
表示为唯一自然数的N
幂和的方法数
示例:X=10,N=2
只有一种方法可以使用低于10的2的幂得到10,那就是1^2+3^2
我的方法
我知道这个问题可能存在一个很好的、优雅的反复出现;但不幸的是我找不到,所以我开始考虑其他方法。我决定从“代码> [1,Z] [1,2,3] < /COD>,因为<代码> 4 ^ 2>10 < /代码>,因此不能是总和为10的(正)数的一部分。在收集了这一系列的数字之后,我把它们都提升到N的幂,然后找到了这个列表中所有子集的排列。所以对于[1,2,3]
我发现[[1],[4],[9],[1,4],[1,9],[4,9],[1,4,9],[1,4,9]
,对于较大的初始数字范围,这不是一系列简单的操作(我的解决方案在最后两次黑客测试中超时)。最后一步是计算总计为X的子列表
解决方案
object Solution {
def numberOfWays(X : Int, N : Int) : Int = {
def candidates(num : Int) : List[List[Int]] = {
if( Math.pow(num, N).toInt > X )
List.range(1, num).map(
l => Math.pow(l, N).toInt
).toSet[Int].subsets.map(_.toList).toList
else
candidates(num+1)
}
candidates(1).count(l => l.sum == X)
}
def main(args: Array[String]) {
println(numberOfWays(readInt(),readInt()))
}
}
以前有人遇到过这个问题吗?如果是这样,还有更优雅的解决方案吗在你建立方格列表之后,剩下的就是我所认为的一种。这是一个古老的NP完全问题。因此,第一个问题的答案是“是”,第二个问题的答案在链接中给出。这可以看作是一个动态规划问题。我仍然有必要对动态规划问题进行推理,因为我就是这样被教导的,但这可能是功能性的
A. Make an array A of length X with type parameter Integer.
B. Iterate over i from 1 to Nth root of X. For all i, set A[i^N - 1] = 1.
C. Iterate over j from 0 until X. In an inner loop, iterate over k from 0 to (X + 1) / 2.
A[j] += A[k] * A[x - k]
D. A[X - 1]
通过跟踪哪些索引是非平凡的,可以稍微提高效率,但效率并没有那么高。def numberOfWays(X:Int,N:Int):Int={
def numberOfWays(X: Int, N: Int): Int = {
def powerSumHelper(sum: Int, maximum: Int): Int = sum match {
case x if x < 1 => 0
case _ => {
val limit = scala.math.min(maximum, scala.math.floor(scala.math.pow(sum, 1.0 / N)).toInt)
(limit to 1 by -1).map(x => {
val y = scala.math.pow(x, N).toInt
if (y == sum) 1 else powerSumHelper(sum - y, x - 1)
}).sum
}
}
powerSumHelper(X, Integer.MAX_VALUE)
}
def powerSumHelper(总和:整数,最大值:整数):整数=总和匹配{
如果x<1=>0,则为情况x
案例=>{
val limit=scala.math.min(最大值,scala.math.floor(scala.math.pow(总和,1.0/N)).toInt)
(限制为1乘-1)。映射(x=>{
valy=scala.math.pow(x,N).toInt
if(y==sum)1 else powerSumHelper(sum-y,x-1)
}).sum
}
}
powerSumHelper(X,整数.MAX_值)
}