我最近解决了一个问题"没有。将数字因子表示为连续数的总和的方法" 我的解决方案是:
int fact_as_sum(int n) { // n is the number whose factorial need to be taken
long int fact=1;
int temp=0,count=0;
for(int i=n;i>0;i--){
fact*=i;
}
printf("%d\n",fact);
for(int i=fact/2;i>0;i--) {
int j=i;
temp=fact;
while(temp>=0) {
if(temp==0) {
count++;
break;
}
else
temp-=j;
j--;
}
}
return count;
}
解决方案工作正确,直到小号。 10!。
但我的解决方案很复杂。 任何人都可以建议一个不太复杂的解决方案吗?
由于
答案 0 :(得分:4)
好的,所以这个问题让我的脑子大为震惊,所以首先要感谢你,我喜欢解决这些问题! 我开始对问题进行数学分析,以便找到最佳实现,然后我想出了这个解决方案:
通过将 n 定义为阶乘结果编号, m 要执行的总和数和 x 添加的起始编号,这一切都细分为以下公式:
现在可以简化,产生以下公式:
这也可以简化,给出以下结果:
求解 x (加法的起始编号),结果为:
现在可以迭代 m 的所有值,以找到所需的 x 值。 m 的下限肯定是0,不可能添加负数量的数字!通过注意 x 应该是正数,可以找到上限,考虑相应正数部分将为空的负值是没有意义的!这给出了以下结果:
产生以下结果:
如前所述, m 的负值被丢弃。
这转换为以下C代码:
console.log(obj.records[i].id)
我已经在几个值上尝试了这个解决方案并编写了测试代码,结果似乎正确。因为阶乘有一个问题,因为阶乘很快达到非常高的值,因此需要更好地管理内存。
希望我提供了一个有趣的解决方案,我很乐意解决它!
如果此解决方案出现问题,请更正。
答案 1 :(得分:1)
不确定。我可以尝试给出一个更简单的解决方案来找到计数:替换
temp = fact;
while(temp>=0) {
if(temp==0) {
count++;
break;
}
else
temp-=j;
j--;
}
通过
if ( fact % j == 0 )
count++;
。这也意味着您不需要temp
,因为您可以使用余数运算符(%
)来检查j
是否为除数(这就是你的内容)试着做那个while循环,对吗?)。
答案 2 :(得分:1)
首先,你的代码有一个错误
1.您需要将i=fact/2
for for循环更改为i=(fact+1)/2;
2.您需要在while循环中添加j > 0
条件以防止无限循环。因为例如temp-(-1)
会增加temp
。
固定代码:
for(long int i=(fact+1)/2; i>0; i--) {
long int j=i;
temp=fact;
while(j > 0 && temp > 0) {
temp-=j;
j--;
if(temp == 0) {
count++;
break;
}
}
}
截至您的问题,可以在O(sqrt(2*N))
时间内完成。以下是一些可以理解的简洁答案:
long int count = 0;
for (long int L = 1; L * (L + 1) < 2 * fact; L++) {
float a = (1.0 * fact-(L * (L + 1)) / 2) / (L + 1);
if (a-(int)a == 0.0)
count++;
}