让 M(n,k)为 k 的所有可能乘法的和 最大可能因素 n 的不同因素,其中订单无关。
例如, M(5,3)= 225 ,因为:
6 + 8 + 10 + 12 + 15 + 20 + 24 + 30 + 40 + 60 = 225。
可以很容易地注意到 C(n,k)这样的乘法,对应于 n中可以选择 k 对象的方式的数量可能的对象。在上面的例子中, C(5,3)= 10 并且确实存在10次这样的乘法,如上所述。
这个问题也可以看作是可能的 n大小的集合,其中包含 k 0's ,其中每个不包含0的单元格具有其值里面有指数+ 1 。例如,一个可能的这样的集合是 {0,2,3,0,5}。从这里开始,需要将集合中不同于0的值相乘。
我的方法是递归算法。类似于上面的定义 M(n,k),我将 M(n,j,k)定义为精确 k 的所有可能乘法的总和具有最大可能因子的因素 n , AND SMALLEST 可能因素 j 。因此,如果继续运行,我的方法将产生所需的值 M(n,1,k)。所以我使用以下代码在 M(n,1,k),上开始递归,用Java编写:
public static long M (long n, long j, long k)
{
if (k==1)
return usefulFunctions.sum(j, n);
for (long i=j;i<=n-k+1+1;i++)
return i*M(n,i+1,k-1);
}
代码说明:
从 n = 5,j = 1,k = 3 开始,只要我们需要更多因子,算法将继续运行,(k> = 1 ),并且由于for循环,它确保只运行不同的因素,因为随着更多因素的增加,这增加了最小可能值 j 。循环运行并减少所需因子的数量,因为它们是“添加”的,这是通过应用实现的 M(n,j + 1,k-1)。 j + 1 确保因子将是不同的,因为因子的最小值增加,并且 k-1 表示我们需要减少1个因子。
函数'sum(j,n)'返回从 j 开始直到 n 的所有数字之和的值,所以的总和(1,10)= 55 即可。这是通过适当,优雅和简单的数学公式完成的,没有循环: sum(j,n)=(n + 1)* n / 2 - (i-1)* i / 2
public static long sum (long i, long n)
{
final long s1 = n * (n + 1) / 2;
final long s2 = i * (i - 1) / 2;
return s1 - s2 ;
}
当 k = 1 时应用此总和的原因,我将用一个例子来解释: 假设我们已经开始使用1 * 2。现在我们需要第三个因子,可以是3,4,5。因为所有乘法:1 * 2 * 3,1 * 2 * 4,1 * 2 * 5都有效,我们可以返回 1 * 2 *(3 + 4 + 5)= 1 * 2 * sum(3, 5)= 24 。
类似的逻辑解释 M(n,j + 1,k-1)旁边的系数“i”。 说我们现在有唯一的因素2.因此我们还需要2个因子,所以我们将2乘以下一个迭代,这应该导致: 2 *(3 *总和(4,5)+ 4 *总和(5,5))
但是,由于我无法解释的原因,代码不起作用。它返回错误的值,并且还有“返回”问题导致函数不返回任何内容,不知道原因。
这就是我在这里发布这个问题的原因,希望有人能帮助我。通过修复此代码或共享他自己的代码。解释我出错的地方将是最明显的。
非常感谢,对这个很长的问题感到抱歉, 马坦。
-----------------------EDIT------------------------
下面是我的固定代码,它解决了这个问题。发布它可能需要它:)玩得开心!
public static long M(long n, long j, long k)
{
if (k == 0)
return 0;
if (k == 1)
return sum(j,n);
else
{
long summation = 0;
for (long i=j; i<=n; i++)
summation += i*M(n, i+1, k-1);
return summation;
}
}
答案 0 :(得分:2)
你的sum函数有问题:这是正确的公式:
public static long sum (long i, long n)
{
double s1 = n*(n+1)/2;
double s2 = i*(i-1)/2;
return (long)(s1-s2);
}
这里有完整的解决方案:
static int n = 5;
static long k = 3;
// no need to add n and k them inside your M function cause they are fixed.
public static long M (long start) // start = 1
{
if(start > k) // if start is superior to k : like your example going from 1..3 , then you return 0
return 0;
int res = 0; // res of your function
for(long i=start+1;i<n;i++){
res+=start*i*sum(i+1,n); // here you take for example 1*2*sum(3,5) + 1*3*sum(4,5).... ect
}
return res+M(start+1); // return res and start again from start+1 wich would be 2.
}
public static long sum (long i, long n)
{
if(i>n)
return 0;
double s1 = n*(n+1)/2;
double s2 = i*(i-1)/2;
return (long)(s1-s2);
}
public static void main(String[] args) {
System.out.println(M(1));
}
希望有所帮助
答案 1 :(得分:2)
我不确定你的算法,但你肯定搞砸了你的sum函数。您遇到的问题与类型转换和整数除法有关。尝试这样的事情:
public static long sum (long i, long n)
{
final long s1 = n * (n + 1) / 2;
final long s2 = (i * i - i) / 2;
return s1 - s2 ;
}
答案 2 :(得分:2)
我看到你得到了你的答案,我真的很喜欢你的算法,但我无法控制自己发布更好的算法。这是想法
M(n,k) = coefficient of x^k in (1+x)(1+2*x)(1+3*x)...(1+n*x)
你可以通过除法和征服算法Click Here来解决上述表达式,找到如何将上面的表达式相乘并以ax^n + bx^(n-1)....+c
整体算法时间复杂度为O(n * log^2 n)
以上算法的最佳部分是
in the attempt of finding solution for M(n,k) , u will find solution for M(n,x) where 1<=x<=n
我希望知道:)