在上述问题中,给定正整数n
,它旨在找到n!
中所有数字的总和。所以这是我的java代码:
public static void main (String[] args) throws java.lang.Exception
{
Scanner sc = new Scanner(System.in);
while(sc.hasNext())
{
int n = sc.nextInt();
BigInteger b = BigInteger.valueOf(1);
for(int i=2;i<=n;i++)
b=b.multiply(BigInteger.valueOf(i));
String s = b.toString();
int sum=0;
for(int i=0;i<s.length();i++)
sum+=(int)(s.charAt(i)-'0');
System.out.println(sum);
}
}
n的限制是n<=1000
。它完美无瑕地工作:
INPUT
5
60
100
1000
输出
3
288
648
10539
但在线评委判断这是一个错误的答案。使用BigInteger
课有什么问题吗?
注意:我想在我的程序中实现BigInteger类中的错误,因为此解决方案没有超出时间限制但给出了错误的答案。
答案 0 :(得分:0)
您的特定情况的一个初始条件是使用Java 8,所以让我们这样做。
首先,如何获得给定输入数的阶乘:
private static final BigInteger TWO = BigInteger.valueOf(2L);
private static BigInteger factorial(final BigInteger inputNumber)
{
BigInteger ret = BigInteger.ONE;
BigInteger b = TWO;
while (b.compareTo(inputNumber) <= 0) {
ret = ret.multiply(b);
b = b.add(BigInteger.ONE);
}
return ret;
}
然后,从那个号码,如何获得位数?我们使用基数10,因此我们可以使用整数除法和模运算符:
private static int digitSum(final BigInteger someInteger)
{
int ret = 0;
BigInteger b = someInteger;
BigInteger[] modResult;
while (b.compareTo(BigInteger.ZERO) > 0) {
modResult = b.divideAndRemainter(BigInteger.TEN);
ret += modResult[1].intValueExact();
b = modResult[0];
}
return ret;
}
现在,将其插入主程序;你应该从一个文件中读取,该文件的输入是整数,每行一个:
public final class FactDigitSum
{
// supposes that the two methods above are defined in this class
private static void printDigitSum(final BigInteger inputNumber)
{
final BigInteger factorial = factorial(inputNumber);
System.out.println(digitSum(factorial));
}
// The main program
public static void main(final String... args)
throws IOException
{
if (args.length == 0)
throw new IllegalArgumentException("No file as argument");
final Path path = Paths.get(args[0]);
try (
final Stream<String> stream = Files.lines(path);
) {
stream.map(BigInteger::new).forEach(FactDigitSum::printDigitSum);
}
}
}
答案 1 :(得分:0)
不要使用字符串。直接从BigInteger计算值。
这应该给你价值。我会把I / O留给你:
public class BigIntFacSum
{
private static int bigFacSum(final int n)
{
int sum = 0;
BigInteger fac = BigInteger.valueOf(2);
BigInteger num = BigInteger.valueOf(3);
for (int i = 3; i <= n; i++)
{
fac = fac.multiply(num);
num = num.add(BigInteger.ONE);
}
while (fac.compareTo(BigInteger.ZERO) > 0)
{
BigInteger[] quotRem = fac.divideAndRemainder(BigInteger.TEN);
fac = quotRem[0];
sum += quotRem[1].intValue();
}
return sum;
}
public static void main(String[] args)
{
System.out.println(bigFacSum(1000));
}
}
这在Java 7中相当快。在Java 8中应该更快,因为它分别使用 Karatsuba 和 Burnikel-Ziegler 优化进行乘法和除法(如据我所知,Java 7没有。)
对于它的价值:如果数字变大,可能通过字符串绕行然后添加字符串中的数字变得更快。在循环中使用divideAndRemainder(BigInteger.TEN)
的天真方式对于像100000!
这样的大数字不适用。我用我自己的BigInteger实现(用不同的语言)尝试了这个,并且字符串绕行对于这样的巨大的nubmers来说要快得多。这是因为使用分而治之算法高度优化了转换为十进制,并且比天真循环更快多。但仅限于相对较大的数字,即远远超过10000!
。 AFAIK,Java使用类似的算法,因此转换为字符串也应该更快,对于类似的大型数据库。
我不知道一种分而治之的算法,它同时计算数字的总和,虽然我不明白它为什么不能。但算法并不简单,mine is not in Java。
但是,这只是作为一个旁边,以防你或其他任何人可能需要这一天。