有人能帮助我解决我犯的错误吗?这是一个简单的问题,可以计算数字的阶乘的尾随零点。
输出在Ideone上可以成功运行,但是由于某些原因抛出
“答案错误”
在SPOJ的编译器上。
有人可以找出我犯的错误。
using System;
public class Test
{
public static void Main(string[] args)
{
int numberOfValues = int.Parse(Console.ReadLine());
int[] values = new int[numberOfValues];
for(int i=0;i<numberOfValues;i++)
{
values[i] = int.Parse(Console.ReadLine());
}
for (int i = 0; i < numberOfValues; i++)
{
Console.WriteLine(calculateFact(values[i]));
}
Console.ReadKey();
}
static int calculateFact(int value)
{
int finalValue = 0;
for (int i = 0; value > 5; i++)
{
value = value / 5;
finalValue += value;
}
return finalValue;
}
}
答案 0 :(得分:3)
现在是实施和运行一些测试来找出“错误答案”的时候了:
using System.Linq;
using System.Numerics;
...
// Slow, ugly but easy to understand and check routine
static int naiveCount(int value) {
BigInteger factorial = 1;
for (int i = 1; i <= value; ++i)
factorial *= i;
return factorial.ToString().Length - factorial.ToString().TrimEnd('0').Length;
}
...
var counterExamples = Enumerable
.Range(0, 100)
.Select(v => new {
value = v,
actual = calculateFact(v),
expected = naiveCount(v), })
.Where(item => item.expected != item.actual)
.Select(item => $"value: {item.value,4} actual: {item.actual,3} expected: {item.expected,3}");
Console.Write(string.Join(Environment.NewLine, counterExamples));
结果:
value: 5 actual: 0 expected: 1
value: 25 actual: 5 expected: 6
value: 26 actual: 5 expected: 6
value: 27 actual: 5 expected: 6
value: 28 actual: 5 expected: 6
value: 29 actual: 5 expected: 6
拥有个计数器示例时,例如calculateFact(5)
情况下调试很容易。现在可以看到问题了吗?在for
循环中:
for (int i = 0; value > 5; i++)
应为(>=
而不是>
)
for (int i = 0; value >= 5; i++)
编辑:从技术上讲,您要做的就是检查5
的幂:
static int calculateFact(int value) {
int result = 0;
// 13 loops = floor(log(2**31)/log(5))
for (int power5 = 5; power5 <= int.MaxValue / 5; power5 *= 5)
result += value / power5;
return result;
}
答案 1 :(得分:1)
您可能会遇到内存不足错误。您不需要int[] values
。您可以在读取数字后立即计算阶乘。而且您不需要Console.ReadKey();
。请注意,我尚未检查calculateFact
的正确性。
正如德米特里(Dmitry)所指出的那样,您的功能有误……您“一气之下”:
for (int i = 0; value >= 5; i++)
看到>=
吗?但是您可以通过删除i
变量来加快速度。
static int calculateFact(int value)
{
int finalValue = 0;
while (true)
{
value /= 5;
if (value == 0)
{
return finalValue;
}
finalValue += value;
}
}
这应该是正确的,但是我不确定它是否足够快(通常SPOJ问题是基于“缓存”数据)