蓝桥杯——试题 算法提高 计算超阶乘
题目:
试题 算法提高 计算超阶乘
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
计算1*(1+k)*(1+2*k)*(1+3*k)*...*(1+n*k-k)的末尾有多少个0,最后一位非0位是多少。
输入格式
输入的第一行包含两个整数n, k。
输出格式
输出两行,每行一个整数,分别表示末尾0的个数和最后一个非0位。
样例输入
15 2
样例输出
0
5
5
数据规模和约定
1<=k<=10,1<=n<=1000000。
思路:
一开始,自己就想着从最后一个数一直往前乘,每次得到一个乘积后就对这个结果进行末尾0的计数,并找到此次最后一位非0的数,直到while循环结束。这里整个循环过程我都没有对ans计算的结果求模,才导致每次提交到OJ都AC不了,以为这里求模了会对结果有影响,所以尝试了很多次改了很多地方,就唯独这个地方没有走心,哎!!!后面看了网友的AC代码,都用了求模,这下才恍然大悟,真的要求模啊,不然数会超越long类型的范围。
没有求模的代码(一开始自己写的):
1 package com.lzp.algorithmAdvance.p2; 2 3 import java.util.Scanner; 4 5 /** 6 * @Author LZP 7 * @Date 2021/3/16 10:17 8 * @Version 1.0 9 * 10 试题 算法提高 计算超阶乘 11 12 13 资源限制 14 时间限制:1.0s 内存限制:256.0MB 15 问题描述 16 计算1*(1+k)*(1+2*k)*(1+3*k)*...*(1+n*k-k)的末尾有多少个0,最后一位非0位是多少。 17 输入格式 18 输入的第一行包含两个整数n, k。 19 输出格式 20 输出两行,每行一个整数,分别表示末尾0的个数和最后一个非0位。 21 样例输入 22 15 2 23 样例输出 24 0 25 5 26 数据规模和约定 27 1<=k<=10,1<=n<=1000000。 28 29 这是我一开始的思路 30 第一下竟然没有想到求模,导致计算的数超过了long,使得结果总是错,每次提交都AC不了 31 */ 32 public class Main { 33 private static int n; 34 private static int k; 35 public static void main(String[] args) { 36 Scanner input = new Scanner(System.in); 37 n = input.nextInt(); 38 k = input.nextInt(); 39 input.close(); 40 41 int end = 1 + (n - 1) * k; 42 long ans = 1; 43 long count = 0; 44 int endNum = -1; 45 while (end > 0) { 46 ans = ans * end; 47 48 String ansStr = String.valueOf(ans); 49 // 找出有多少个零 50 int index = ansStr.length() - 1; 51 while (ansStr.charAt(index) == '0') { 52 index--; 53 } 54 // 每次找最新的最后一位非0位是多少。 55 endNum = Integer.parseInt(ansStr.substring(index, index + 1)); 56 // 不包括index本身 57 int zNum = ansStr.length() - 1 - index; 58 if (zNum > 0) { 59 count += zNum; 60 ans = Long.parseLong(ansStr.substring(0, index + 1)); 61 } 62 end -= k; 63 64 // 就是因为没有求模,才导致一次次提交都错 65 // ans %= 10000000; // 一开始没有这一行 66 } 67 68 System.out.println(count); 69 System.out.println(endNum); 70 } 71 }
AC代码:
1 package com.lzp.algorithmAdvance.p2; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 import java.util.Scanner; 6 7 /** 8 * @Author LZP 9 * @Date 2021/3/16 10:17 10 * @Version 1.0 11 * 12 试题 算法提高 计算超阶乘 13 14 15 资源限制 16 时间限制:1.0s 内存限制:256.0MB 17 问题描述 18 计算1*(1+k)*(1+2*k)*(1+3*k)*...*(1+n*k-k)的末尾有多少个0,最后一位非0位是多少。 19 输入格式 20 输入的第一行包含两个整数n, k。 21 输出格式 22 输出两行,每行一个整数,分别表示末尾0的个数和最后一个非0位。 23 样例输入 24 15 2 25 样例输出 26 0 27 5 28 数据规模和约定 29 1<=k<=10,1<=n<=1000000。 30 31 */ 32 public class MainAC { 33 private static int n; 34 private static int k; 35 public static void main(String[] args) { 36 Scanner input = new Scanner(System.in); 37 n = input.nextInt(); 38 k = input.nextInt(); 39 input.close(); 40 41 // 用于记录0的个数 42 int count = 0; 43 long sum = 1; 44 // i从 1~n-1 45 for (long i = 1; i < n; i++) { 46 sum *= (1 + (i * k)); 47 // 去0 这里要求sum > 9是为了防止sum = 0的情况,如果sum真的等于0的话,那么后面跟sum相乘就会全为0 48 while (sum % 10 == 0 && sum > 9) { 49 sum /= 10; 50 count++; 51 } 52 // 防止超过long,就得求模 53 sum %= 1000000; 54 } 55 System.out.println(count); 56 System.out.println(sum % 10); 57 } 58 59 }