【问题标题】:Calculate the number of trailing zeroes in a sequence计算序列中尾随零的数量
【发布时间】:2018-11-06 00:32:24
【问题描述】:

考虑s(0) 和s(1) 是输入的序列,s(n) = s(n-1) * s(n-2) 是所有n >= 2。我想在s(n) 中找到尾随零的数量。我们可以假设:

  • n、s(0) 和 s(1) 作为输入给出
  • n <= 40
  • s(0) <= 20
  • s(1) <= 20

以下是我的代码尝试。 n 大于 30 时不运行(运行时间很长)。还有其他方法可以计算尾随零的数量吗?

public class Soroco {

  public static void main(String[] args) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    BigInteger n = new BigInteger(br.readLine());
    BigInteger s0 = new BigInteger(br.readLine());
    BigInteger s1 = new BigInteger(br.readLine());
    BigInteger num = s(n, s0, s1);
    System.out.println(num);
    System.out.println(countTrailingZeroes(num));
  }

  static BigInteger s(BigInteger n, BigInteger s0, BigInteger s1) {
    if (n.equals(new BigInteger("0")))
        return s0;
    else if (n.equals(new BigInteger("1")))
        return s1;
    else {
        BigInteger n1=n.subtract(new BigInteger("1"));
        BigInteger n2=n.subtract(new BigInteger("2"));
        BigInteger n3=s(n1, s0, s1).multiply(s(n2, s0, s1));
        return n3;
    }
  }

  static int countTrailingZeroes(BigInteger num) {
    String str = String.valueOf(num);
    int count = 0;
    for (int i = 0; i < str.length(); i++)
        if (str.charAt(i) == '0')
            count++;
    return count;
  }
}

【问题讨论】:

  • 数对 5 和 2 和 10 的幂
  • Pkpnd 知道他的东西,阅读他的答案
  • 如何计算一个数字中 2 的个数和 5 的个数

标签: java recursion sequence multiplication


【解决方案1】:
public static void main(String[] args) throws IOException {

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    int n = Integer.parseInt(br.readLine());

    int s0 = Integer.parseInt(br.readLine());

    int s1 = Integer.parseInt(br.readLine());

    int num21 = findNumberOf2s(s0);

    int num22 = findNumberOf2s(s1);

    int num51 = findNumberOf5s(s0);

    int num52 = findNumberOf5s(s1);

    int arr2[] = new int[n + 1];
    arr2[0] = num21;
    arr2[1] = num22;
    for (int i = 2; i <= n; i++)
        arr2[i] = arr2[i - 1] + arr2[i - 2];

    int arr5[] = new int[n + 1];
    arr5[0] = num51;
    arr5[1] = num52;
    for (int i = 2; i <= n; i++)
        arr5[i] = arr5[i - 1] + arr5[i - 2];

    System.out.println(Math.min(arr2[n], arr5[n]));

}

static int findNumberOf2s(int num) {
    int num2 = 0;
    while (num % 2 == 0) {
        num = num / 2;
        num2++;
    }
    return num2;
}

static int findNumberOf5s(int num) {
    int num5 = 0;
    while (num % 5 == 0) {
        num = num / 5;
        num5++;
    }
    return num5;
}

【讨论】:

    【解决方案2】:

    不需要执行整个乘法,您只需要跟踪 2 和 5 的因数。如果一个数字可以写为N = 2^a * 5^b * (factors other than 2 or 5),那么N 中尾随零的数量为min(a, b)。 (这是因为尾随零只是 10 的因数,需要一个 2 和一个 5。)

    请注意,乘法将因子的指数相加。所以,如果你能写:

    s(n-2) = 2^a * 5^b * (factors other than 2 or 5)
    s(n-1) = 2^c * 5^d * (factors other than 2 or 5)
    

    那么我们有:

    s(n) = s(n-1) * s(n-2)
         = 2^(a+c) * 5^(b+d) * (factors other than 2 or 5)
    

    因此,我们可以将这个问题视为两个Fibonacci sequences。您从s(0) 和s(1) 中的2 和5 的数量开始,并以斐波那契序列的方式计算s(2), s(3), ..., s(n) 中的2 和5 的数量:

    #2s in s(n) = (#2s in s(n-1)) + (#2s in s(n-2))
    #5s in s(n) = (#5s in s(n-1)) + (#5s in s(n-2))
    

    最后,尾随零的数量是min(#2s in s(n), #5s in s(n))。


    上述算法(如果使用循环或记忆递归实现)是O(n)。您的尝试在n 中呈指数级增长,这就是为什么即使n = 30 也需要很长时间才能运行。我并不是要抨击您的尝试,但最好理解这些错误——您的代码运行缓慢主要有两个原因:

    首先,将非常大的整数与完全精度相乘(就像您对BigInteger 所做的那样)非常慢,因为每次乘法时位数可能会翻倍。如果您只关心尾随零的数量,则不需要完全精确。

    其次,忽略乘法的成本,您对 s 的递归实现仍然是指数时间,但不一定是。请注意,您多次计算相同的值——s(n-2) 是分别为s(n) 和s(n-1) 计算的,但s(n-2) 的值显然是相同的。诀窍是通过记住先前计算的结果来memoize the recursion,以避免重新计算。或者,您可以使用循环计算类似斐波那契的序列:

    // Computes the n-th Fibonacci number in O(n) time
    int[] fib = new int[n + 1];
    fib[0] = 0;
    fib[1] = 1;
    for (int i = 2; i <= n; i++)
        fib[i] = fib[i-1] + fib[i-2];
    return fib[n];
    

    这是一种比记忆递归简单得多的方法,至少对于这个问题而言。

    【讨论】:

    • 如何计算一个数字中 2 的个数和 5 的个数
    • 更简单的方法是将数字转换为字符串,然后检查所需的数字。如果不是,您可以通过每次将数字除以 10 并检查余数来艰难地前进。如果余数是您需要的数字,很好..
    • @mavericktz 您可以反复除以 2 或 5,直到数字不再可整除。 int num2 = 0; while (n % 2 == 0) { n /= 2; num2++; }
    • @Sparker0i 我们讨论的是质因数分解中 2 或 5 的数量。您的建议将给出尾随 2 或 5 的数量,这是完全不同的。
    • @pkpnd thanx,得到了解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-11
    • 1970-01-01
    • 1970-01-01
    • 2020-08-23
    • 2020-05-11
    • 2014-01-11
    相关资源
    最近更新 更多